Skip to content

Instantly share code, notes, and snippets.

@nikic
Created January 31, 2012 15:41
Show Gist options
  • Save nikic/1711140 to your computer and use it in GitHub Desktop.
Save nikic/1711140 to your computer and use it in GitHub Desktop.
Tagged pointer sample implementation
#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