proxygen
|
#include <StampedPtr.h>
Public Member Functions | |
T * | ptr () const |
uint16_t | stamp () const |
void | set (T *ptr, uint16_t stamp) |
void | setPtr (T *ptr) |
void | setStamp (uint16_t stamp) |
Static Public Member Functions | |
static T * | unpackPtr (uint64_t raw) |
static uint16_t | unpackStamp (uint64_t raw) |
static uint64_t | pack (T *ptr, uint16_t stamp) |
Public Attributes | |
uint64_t | raw |
Static Private Attributes | |
static constexpr unsigned | kInternalStampBits = sizeof(void*) == 4 ? 32 : 16 |
StampedPtr packs both a pointer to T and a uint16_t into a 64-bit value, exploiting the fact that current addresses are limited to 48 bits on all current x86-64 and ARM64 processors.
For both x86-64 and ARM64, 64-bit pointers have a canonical form in which the upper 16 bits are equal to bit 47. Intel has announced a 57-bit addressing mode (see https://software.intel.com/ sites/default/files/managed/2b/80/5-level_paging_white_paper.pdf), but it is not yet available. The first problematic platform will probably be ARMv8.2, which supports 52-bit virtual addresses.
This code works on all of the platforms I have available for test, and probably on all currently-shipping platforms that have a hope of compiling folly. Rather than enumerating the supported platforms via ifdef, this code dynamically validates its packing assumption in debug builds on each call to a mutating function. Presumably by the time we are running this process in an operating system image that can address more than 256TB of memory, RAM cost and the latency of 128-bit CAS will have improved enough that this optimization is no longer impactful.
A common approach to this kind of packing seems to be to just assume the top 16 bits are zero, but https://github.com/LuaJIT/LuaJIT/issues/49 indicates that ARM64 platforms in the wild are actually setting bit 47 in their stack addresses. That means that we need to extend bit 47 to do the right thing (it's not expensive, it compiles to one instruction on x86-64 and arm64).
Compare to PackedSyncPtr and DiscriminatedPtr, which perform similar packing but add additional functionality. The name is taken from Java's AtomicStampedReference. Unlike PackedSyncPtr, which tries to act pointer-like, this class acts more like a pair whose elements are named ptr and stamp. It also allows direct access to the internal raw field: since we're already at the metal you might want to play additional games. It is guaranteed that a zero raw value gets decoded as a (ptr,stamp) of (nullptr,0).
Definition at line 63 of file StampedPtr.h.
|
inlinestatic |
Definition at line 106 of file StampedPtr.h.
References FOLLY_SAFE_DCHECK, folly::StampedPtr< T >::kInternalStampBits, folly::StampedPtr< T >::ptr(), folly::StampedPtr< T >::raw, folly::StampedPtr< T >::stamp(), uint64_t, folly::StampedPtr< T >::unpackPtr(), and folly::StampedPtr< T >::unpackStamp().
Referenced by folly::makeStampedPtr(), folly::StampedPtr< T >::set(), folly::StampedPtr< T >::setPtr(), and folly::StampedPtr< T >::setStamp().
|
inline |
Definition at line 72 of file StampedPtr.h.
References folly::StampedPtr< T >::unpackPtr().
Referenced by folly::StampedPtr< T >::pack(), and TEST().
|
inline |
Definition at line 80 of file StampedPtr.h.
References folly::StampedPtr< T >::pack(), and folly::StampedPtr< T >::stamp().
Referenced by TEST().
|
inline |
Definition at line 84 of file StampedPtr.h.
References folly::StampedPtr< T >::pack(), and folly::StampedPtr< T >::unpackStamp().
Referenced by TEST().
|
inline |
Definition at line 88 of file StampedPtr.h.
References folly::StampedPtr< T >::pack(), and folly::StampedPtr< T >::unpackPtr().
Referenced by TEST().
|
inline |
Definition at line 76 of file StampedPtr.h.
References folly::StampedPtr< T >::unpackStamp().
Referenced by folly::StampedPtr< T >::pack(), folly::StampedPtr< T >::set(), and TEST().
|
inlinestatic |
Definition at line 92 of file StampedPtr.h.
References int64_t, folly::StampedPtr< T >::kInternalStampBits, folly::StampedPtr< T >::raw, and folly::T.
Referenced by folly::StampedPtr< T >::pack(), folly::StampedPtr< T >::ptr(), and folly::StampedPtr< T >::setStamp().
|
inlinestatic |
Definition at line 102 of file StampedPtr.h.
References folly::StampedPtr< T >::raw, and uint16_t.
Referenced by folly::StampedPtr< T >::pack(), folly::StampedPtr< T >::setPtr(), and folly::StampedPtr< T >::stamp().
|
staticprivate |
Definition at line 120 of file StampedPtr.h.
Referenced by folly::StampedPtr< T >::pack(), and folly::StampedPtr< T >::unpackPtr().
uint64_t folly::StampedPtr< T >::raw |
The packing is not guaranteed, except that it is guaranteed that raw == 0 iff ptr() == nullptr && stamp() == 0.
Definition at line 68 of file StampedPtr.h.
Referenced by folly::StampedPtr< T >::pack(), TEST(), folly::StampedPtr< T >::unpackPtr(), and folly::StampedPtr< T >::unpackStamp().