The delayed atomicity mechanism allows you to prepare a set of persistent changes and delay their publication to the persistent state until a specific moment. This is useful for implementing algorithms with relaxed consistency guarantees.
Key Concepts
- Atomicity: Publication is fail-safe atomic for the entire collection of actions. If the program exits before publication or if actions are canceled, any reserved resources are automatically released back to the pool.
- Action Representation: A single action is represented by a
struct pobj_action. Functions that create actions populate this structure, while functions that publish actions take an array of these structures and the array size. - Thread Safety: Actions can be created in one thread and published in another.
- Lifecycle: When creating an action, the
act argument must be a non-NULL pointer to a struct pobj_action. This structure must not be modified or deallocated until after the actions have been published.
Workflow Example
- Reserve: Use
pmemobj_reserve() to reserve space. The object can be modified in memory, but changes are not yet part of the persistent state's atomic view. - Prepare: Use
pmemobj_set_value() or pmemobj_defer_free() to queue the intended changes. - Publish: Use
pmemobj_publish() to atomically apply all queued actions to the persistent state. - Cancel: If something goes wrong before publication, use
pmemobj_cancel() to release reserved resources and invalidate the actions.
/* reserve, populate and persist the first object */
PMEMoid tail = pmemobj_reserve(pop, &actv[0], sizeof(struct list_node), 0);
if (TOID_IS_NULL(tail))
return -1;
D_RW(tail)->value = 1;
D_RW(tail)->next = OID_NULL;
pmemobj_persist(pop, D_RW(tail), sizeof(struct list_node));
/* ... prepare other actions ... */
/* atomically publish the above actions */
pmemobj_publish(pop, actv, 4);