ObjectStore Class Reference
HiCR
|
#include <objectStore.hpp>
Public Member Functions | |
ObjectStore (CommunicationManager &communicationManager, GlobalMemorySlot::tag_t tag, MemoryManager &memoryManager, std::shared_ptr< MemorySpace > memorySpace, Instance::instanceId_t instanceId) | |
~ObjectStore ()=default | |
std::shared_ptr< MemorySpace > | getMemorySpace () const |
__INLINE__ std::shared_ptr< DataObject > | createObject (void *ptr, size_t size, blockId id) |
__INLINE__ std::shared_ptr< DataObject > | createObject (std::shared_ptr< LocalMemorySlot > slot, blockId id) |
__INLINE__ void | publish (std::shared_ptr< DataObject > dataObject) |
__INLINE__ std::shared_ptr< LocalMemorySlot > | get (DataObject &dataObject) |
__INLINE__ void | destroy (DataObject &dataObject) |
__INLINE__ handle | serialize (DataObject &dataObject) |
__INLINE__ std::shared_ptr< DataObject > | deserialize (const handle &handle) |
__INLINE__ bool | fence () |
__INLINE__ bool | fence (const std::shared_ptr< DataObject > &dataObject) |
Detailed Description
This is the front-end, managing entity for the object store. Multiple instances of this class can be created, one for each tag.
It has a role similar to core HiCR's Manager classes, hence it uses these managers as dependencies. The ObjectStore is responsible for the management of data-objects/blocks.
A block is a globally unique reference to a memory region that exists somewhere on the system. It is created via a call to createObject, and published (i.e. made available for access) via a call to publish.
A block has an owner, which initially is the worker that created the block via a call to publish. An owner of a block is not necessarily an active participant on all activities on said block– in fact, most operations on blocks are asynchronous while the core functionality, i.e., reading a block and benefit of one-sided fencing. Staying passive while subject to remote reads, however, does require the underlying system to natively support it.
A block at a worker which is not the owner of the block will, after the first call to get, return a pointer to the block contents for read-only access. At non-owner locations, the returned memory pointer need not point to a copy of the owner's memory – consider, e.g., a shared-memory object store impementation, or a sophisticated network fabric with GAS-like functionalities.
The memory area returned by get will not necessarily be kept up to date with the contents at the owner side. Successive calls to get may be used to re-synchronise with the owner.
A call to publish is not collective, meaning that remote workers will not immediately be able to refer to any remotely published block. For remote workers to be able to refer to a block, a serialized handle to the block should be copied to the remote workers that want to make use of it (e.g., by using channels or raw memory copies).
Therefore, such handles of the HiCR::objectStore::DataObject shall be copyable, in the exact sense of the corresponding C++ type trait. This informally means it can both be the target for raw memcpy calls as well as the target for inter-worker communication. Copying allows for remote workers to refer to blocks it did not (initially) own.
Multiple instances of the same block on the same worker will always refer to the same memory (i.e., the pointer returned by get will equal when called on the same blocks on the same worker).
On non-owner workers, a call to get asynchronously initiates the data movement from the owner to the non-owner, so that the non-owner local block memory reflects the contents of the owner of the block. This copy is only guaranteed to have completed at the end of a subsequent call to fence. Before this call to fence, the contents of the pointer returned by get are undefined.
Accordingly, the block data at the owner worker should be immutable while other non-owner workers have issued calls to get– otherwise, partially updated and partially non-updated contents may be received, leading to inconsistent states. To indicate to the owner that any pending reads have completed (and thus that it may safely modify its data), again a call to fence should be made.
A call to fence is a blocking function. A non-blocking variant may in the future be provided by test_fence().
Constructor & Destructor Documentation
◆ ObjectStore()
|
inline |
Constructor
- Parameters
-
[in] communicationManager The communication manager of the HiCR instance. [in] tag The tag to associate with the object store. [in] memoryManager The memory manager of the HiCR instance. [in] memorySpace The memory space the object store operates in. [in] instanceId The ID of the instance running the object store. (Created objects will have this instance ID)
◆ ~ObjectStore()
|
default |
Default Destructor
Member Function Documentation
◆ createObject() [1/2]
|
inline |
Creates a new data object from an existing LocalMemorySlot. The calling worker will be the owner of the returned Data Object.
- Parameters
-
[in] slot The local memory slot to create the block from. [in] id The ID of the block to be created.
- Returns
- A DataObject referring to the memory slot.
◆ createObject() [2/2]
|
inline |
Creates a new data object from a given memory allocation. The calling worker will be the owner of the returned Data Object.
- Parameters
-
[in] ptr The pointer to the memory region. [in] size The size of the memory region. [in] id The ID of the block to be created.
- Returns
- A DataObject referring to the memory region.
◆ deserialize()
|
inline |
Deserialize a handle to a data object. The handle is a trivially copiable, serialized representation of a data object.
- Parameters
-
[in] handle The handle to deserialize.
- Returns
- A shared pointer to the deserialized data object.
◆ destroy()
|
inline |
Destroy a data object. This is a local operation, does not affect other copies of the data object. The data object is removed from the object store and the associated memory slots are freed.
The local slot is only freed if the data object is a fetched object, originating from a call to get. On the owner instance, the user is responsible for freeing the local memory slot. The global slot is always destroyed, if present.
- Parameters
-
[in] dataObject The data object to destroy.
◆ fence() [1/2]
|
inline |
Fences all block activity of the object store instance.
This is a collective, blocking call. All workers that have communications in the object store must make the same number of calls to fence. This (paradoxically) allows for fully asynchronous fencing.
- Warning
- I.e., a call to fence on one party may exit before a matching call elsewhere has finished: a call to this function does not imply a barrier.
A call to this function is not thread-safe.
- Returns
true
if the fence has completed;false
otherwise.
◆ fence() [2/2]
|
inline |
Fences locally on a specific data object.
This is a one-sided, blocking call; returning from this function indicates that, specific to this data object, incoming memory movement (ie. a get()) has completed.
- Parameters
-
[in] dataObject The data object to fence.
- Returns
true
if the fence has completed;false
otherwise.
◆ get()
|
inline |
Retrieve a pointer to the block contents.
Multiple instances of the same block on the same worker will always refer to the same memory (i.e., the pointer returned by get will equal when called on the same blocks on the same worker). If the block is not found in the object store, ie. it has not been published, or the relevant update has not finished, a nullptr will be returned.
On non-owner workers, a call to get asynchronously initiates the data movement from the owner to the non-owner, so that the non-owner local block memory reflects the contents of the owner of the block. This copy is only guaranteed to have completed at the end of a subsequent call to fence. Before this call to fence, the contents of the pointer returned by get are undefined.
- Parameters
-
[in] dataObject The data object to get.
- Returns
- A pointer to the memory slot that contains the block contents, or a nullptr if the block is not found.
The contents are guaranteed to match with the owner's after the next call to fence over the given ID.
A call to this function implies
- Note
- The intent is that this upper bound on work occurs at most once per block, and only in the case that retrieval first requires the allocation of a local buffer.
A call to this function is non-blocking, since the contents of the memory the return value points to are undefined until the next call to fence. This function is one-sided and (thus) not collective.
Repeated calls to this function with the same ID but without any intermediate calls to fence with that ID will behave as though only a single call was made.
A call to this function shall be thread-safe.
- Note
- The thread-safety plus re-entrant-safety means the implementation of this function must include an atomic guard that is unlocked at a call to fence.
◆ getMemorySpace()
|
inline |
Get the memory space the object store operates in.
- Returns
- The memory space the object store operates in.
◆ publish()
|
inline |
Publishes a block to the object store.
A call to this function is not thread-safe.
- Parameters
-
[in] dataObject The data object to publish.
◆ serialize()
|
inline |
Produce a serialized representation (handle) of a data object. This representation is trivially copyable and can be sent over the network.
- Parameters
-
[in] dataObject The data object to serialize.
- Returns
- A handle to the data object.
The documentation for this class was generated from the following file:
- /home/runner/work/HiCR/HiCR/include/hicr/frontends/objectStore/objectStore.hpp
Generated by