Created
January 31, 2012 15:41
-
-
Save nikic/1711140 to your computer and use it in GitHub Desktop.
Tagged pointer sample implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <cassert> | |
// alignedTo defaults to 8 (on 64 bit) | |
template <typename T, int alignedTo = sizeof(T *)> | |
class TaggedPointer { | |
private: | |
static_assert( | |
alignedTo != 0 && ((alignedTo & (alignedTo - 1)) == 0), | |
"Alignment parameter must be power of two" | |
); | |
// tagMask = alignedTo - 1 = 7 = 0b111 | |
// i.e. the lowest three bits are set, which is where the tag is stored | |
static const size_t tagMask = alignedTo - 1; | |
// pointerMask is the exact contrary: 0b...11111000 | |
// i.e. all bits apart from the three lowest are set, which is where the pointer is stored | |
static const size_t pointerMask = ~tagMask; | |
// Save us some reinterpret_casts with a union | |
union { | |
T *asPointer; | |
size_t asBits; | |
}; | |
public: | |
inline TaggedPointer(T *pointer = 0, int tag = 0) { | |
set(pointer, tag); | |
} | |
inline void set(T *pointer, int tag = 0) { | |
// make sure that the pointer really is aligned | |
assert((reinterpret_cast<size_t>(pointer) & tagMask) == 0); | |
// make sure that the tag isn't too large | |
assert((tag & pointerMask) == 0); | |
asPointer = pointer; | |
asBits |= tag; | |
} | |
inline T *getPointer() { | |
return reinterpret_cast<T *>(asBits & pointerMask); | |
} | |
inline int getTag() { | |
return asBits & tagMask; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment