carb::extras::HandleDatabase
Defined in carb/extras/HandleDatabase.h
- 
template<class Mapped, class Handle, class Allocator = std::allocator<Mapped>>
 class HandleDatabase
- Provides an OS-style mapping of a Handle to a Resource. - Essentially HandleDatabase is a fast thread-safe reference-counted associative container. - A given Handle value is typically never reused, however, it is possible for a handle value to be reused if billions of handles are requested. - Thread Safety
- Unless otherwise mentioned, HandleDatabase functions may be called simultaneously from multiple threads. 
 - The HandleDatabase can store at most - (2^31)-1items, or 2,147,483,647 items simultaneously, provided the memory exists to support it.- Implementation Details: - HandleDatabase achieves its speed and thread-safety by having a fixed-size base array ( - m_database) where each element is an array of size 2^(base array index). As such, these arrays double the size of the previous index array. These base arrays are never freed, simplifying thread safety and allowing HandleDatabase to be mostly lockless. This array-of-arrays forms a non-contiguous indexable array where the base array and offset can be computed from a 32-bit index value (see- indexToBucketAndOffset).- The Handle is a 64-bit value composed of two 32-bit values. The least-significant 32 bits is the index value into the array-of-arrays described above. The most-significant 32 bits is a lifecycle counter. Every time a new Mapped object is constructed, the lifecycle counter is incremented. This value forms a contract between a handle and the Mapped object at the index indicated by the Handle. If the lifecycle counter doesn’t match, the Handle is invalid. As this lifecycle counter is incremented, there is the possibility of rollover after 2^31 handles are generated at a given index. The most significant bit will then be set as a rollover flag so that handleWasValid() continues to operate correctly. The handleWasValid() function returns - truefor any Handle where the lifecycle counter at the given index is greater-than-or-equal to the Handle’s lifecycle counter, or if the rollover flag is set.- Template Parameters
- Mapped – The “value” type that is associated with a Handle. 
- Handle – The “key” type. Must be an unsigned integer or pointer type and 64-bit. This is an opaque type that cannot be dereferenced. 
- Allocator – The allocator that will be used to allocate memory. Must be capable of allocating large contiguous blocks of memory. 
 
 - Public Types - 
using HandleRefType = HandleRef<Mapped, Handle, Allocator>
- An alias to the HandleRef for this HandleDatabase. 
 - 
using ConstHandleRefType = ConstHandleRef<Mapped, Handle, Allocator>
- An alias to the ConstHandleRef for this HandleDatabase. 
 - 
using scoped_handle_ref_type = HandleRefType
- Deprecated: Use HandleRefType instead. 
 - Public Functions - 
inline constexpr HandleDatabase() noexcept
- Constructor. - Thread Safety
- The constructor must complete in a single thread before any other functions may be called on - *this.
 
 - 
inline ~HandleDatabase()
- Destructor. - Thread Safety
- All other functions on - *thismust be finished before the destructor can be called.
 
 - 
inline bool handleWasValid(Handle handle) const
- Checks to see if a handle is valid or was ever valid in the past. - Parameters
- handle – The Handle to check. 
- Returns
- trueif a- handleis currently valid or was valid in the past and has since been released;- falseotherwise.
 
 - 
inline bool handleIsValid(Handle handle) const
- Checks to see if a handle is currently valid. - Parameters
- handle – The Handle to check. 
- Returns
- trueif a- handleis currently valid;- falseotherwise.
 
 - 
template<class ...Args>
 inline std::pair<Handle, Mapped*> createHandle(Args&&... args)
- Creates a new Mapped type with the given arguments. - Parameters
- args – The arguments to pass to the Mapped constructor. 
- Returns
- A - std::pairof the Handle that can uniquely identify the new Mapped type, and a pointer to the newly constructed Mapped type.
 
 - 
inline Mapped *getValueFromHandle(Handle handle) const
- Attempts to find the Mapped type represented by - handle.- Thread Safety
- Not thread-safe as the Mapped type could be destroyed if another thread calls release(). 
 - Parameters
- handle – A handle previously returned from createHandle(). Invalid or previously-valid handles will merely result in a - nullptrresult without an assert or any other side-effects.
- Returns
- A pointer to a valid Mapped type if the handle was valid; - nullptrotherwise.
 
 - 
inline Handle getHandleFromValue(const Mapped *mapped) const
- Retrieves the Handle representing - mapped.- Warning - Providing - mappedthat is no longer valid or was not returned from one of the HandleDatabase functions is undefined.- Parameters
- mapped – A Mapped type previously created with createHandle(). 
- Returns
- The Handle representing - mapped.
 
 - 
inline Mapped *tryAddRef(Handle handle)
- Atomically attempts to add a reference for the given Handle. - Parameters
- handle – A handle previously returned from createHandle(). Invalid or previously-valid handles will merely result in a - nullptrresult without an assert or any other side-effects.
- Returns
- A pointer to a valid Mapped type if a reference could be added; - nullptrotherwise.
 
 - 
inline void addRef(Handle handle)
- Atomically adds a reference for the given Handle; fatal if - handleis invalid.- Parameters
- handle – A valid handle previously returned from createHandle(). Invalid or previously-valid handles will result in - std::terminate()being called.
 
 - 
inline void addRef(Mapped *mapped)
- Atomically adds a reference for the Handle representing - mapped.- Warning - Providing - mappedthat is no longer valid or was not returned from one of the HandleDatabase functions is undefined.- Parameters
- mapped – A Mapped type previously created with createHandle(). 
 
 - 
inline bool release(Handle handle)
- Atomically releases a reference for the given Handle, potentially freeing the associated Mapped type. - Parameters
- handle – A valid handle previously returned from createHandle(). Invalid or previously-valid handles will result in an assert in Debug builds, but return - falsewith no side effects in Release builds.
- Returns
- trueif the last reference was released and- handleis no longer valid;- falseif Handle is not valid or is previously-valid or a non-final reference was released.
 
 - 
inline bool release(Mapped *mapped)
- Atomically releases a reference for the Handle representing - mapped.- Warning - Provided - mappedthat is no longer valid or was not returned from one of the HandleDatabase functions is undefined.- Parameters
- mapped – A Mapped type previously created with createHandle(). 
- Returns
- trueif the last reference was released and- mappedis no longer valid;- falseif a reference other than the last reference was released.
 
 - 
inline bool releaseIfLastRef(Handle handle)
- Atomically releases a reference if and only if it’s the last reference. - Parameters
- handle – A valid handle previously returned from createHandle(). Invalid or previously-valid handles will result in an assert in Debug builds, but return - falsewith no side effects in Release builds.
- Returns
- trueif the last reference was released and- handleis no longer valid;- falseotherwise.
 
 - 
inline bool releaseIfLastRef(Mapped *mapped)
- Atomically releases a reference if and only if it’s the last reference. - Warning - Provided - mappedthat is no longer valid or was not returned from one of the HandleDatabase functions is undefined.- Parameters
- mapped – A Mapped type previously created with createHandle(). 
- Returns
- trueif the last reference was released and- mappedis no longer valid;- falseotherwise.
 
 - 
inline HandleRefType makeScopedRef(Handle handle)
- Attempts to atomically add a reference to - handle, and returns a HandleRef to- handle.- Parameters
- handle – A handle previously returned from createHandle(). Invalid or previously-valid handles will merely result in an empty HandleRef result without an assert or any other side-effects. 
- Returns
- If tryAddRef() would return a valid Mapped type for - handle, then a HandleRef that manages the reference is returned; otherwise an empty HandleRef is returned.
 
 - 
inline ConstHandleRefType makeScopedRef(Handle handle) const
- Attempts to atomically add a reference to - handle, and returns a ConstHandleRef to- handle.- Parameters
- handle – A handle previously returned from createHandle(). Invalid or previously-valid handles will merely result in an empty ConstHandleRef result without an assert or any other side-effects. 
- Returns
- If tryAddRef() would return a valid Mapped type for - handle, then a ConstHandleRef that manages the reference is returned; otherwise an empty ConstHandleRef is returned.
 
 - 
template<class Func>
 inline void forEachHandle(Func &&f) const
- Calls the provided - Funcinvocable object for each valid handle and its associated mapped type.- Thread Safety
- The - Mapped*passed to- fis not safe to use if any other thread would be calling releaseIfLastRef() or release() to release the last reference of a Handle. In these situations it is instead recommended to try to add a reference to the- Handlepassed to- fin order to assure validity.
 - Parameters
- f – An invocable object with signature - void(Handle, Mapped*). Note that there also exists a version of- forEachHandlethat can accept- bool(Handle, Mapped*)and can early out. Technically any non-bool return type is allowed but any return values are ignored. It is highly recommended to ignore the- Mapped*unless it is guaranteed that no other threads may be modifying the- HandleDatabase, in which case it is recommend to instead try to add a reference to the- Handlein order to assure validity.
 
 - 
template<class Func>
 inline bool forEachHandle(Func &&f) const
- Calls the provided - Funcinvocable object for each valid handle and its associated mapped type until the invocable object returns- false.- Thread Safety
- The - Mapped*passed to- fis not safe to use if any other thread would be calling releaseIfLastRef() or release() to release the last reference of a Handle. In these situations it is instead recommended to try to add a reference to the- Handlepassed to- fin order to assure validity.
 - Parameters
- f – An invocable object with signature - bool(Handle, Mapped*). If the invocable object returns- false, iteration terminates immediately and returns- false. It is highly recommended to ignore the- Mapped*unless it is guaranteed that no other threads may be modifying the- HandleDatabase, in which case it is recommend to instead try to add a reference to the- Handlein order to assure validity.
- Returns
- trueif iteration completed over the entirety of- *this;- falseif- freturned- falsecausing iteration to be aborted early.
 
 - 
inline size_t clear()
- Iterates over all valid handles and sets their reference counts to zero, destroying the associated mapped type. - Thread Safety
- This function is NOT safe to call if any other thread is calling ANY other HandleDatabase function except for clear() or handleWasValid(). 
 - Returns
- The number of handles that were released to zero.