117
memory because all allocations and object construction/destruction must be done
atomically with respect to power-fail interruptions. The transactional allocations use
perfect forwarding and variadic templates for object construction. This makes object
creation similar to calling the constructor and identical to std::make_shared. The
transactional array creation, however, requires the objects to be default constructible.
The created arrays can be multidimensional. The pmem::obj::make_persistent and
pmem::obj::make_persistent_array must be called within a transaction; otherwise, an
exception is thrown. During object construction, other transactional allocations can be
made, and that is what makes this API very flexible. The specifics of persistent memory
required the introduction of the pmem::obj::delete_persistent function, which
destroys objects and arrays of objects. Since the pmem::obj::persistent_ptr does not
automatically handle the lifetime of pointed to objects, the user is responsible for disposing
of the ones that are no longer in use. Listing 8-3 shows example of transaction allocation.
Atomic allocations behave differently as they do not return a pointer. Developers
must provide a reference to one as the function’s argument. Because atomic allocations
are not executed in the context of a transaction, the actual pointer assignment must be
done through other means. For example, by redo logging the operation. Listing 8-3 also
provides an example of atomic allocation.
Listing 8-3. Example of transactional and atomic allocations
39
struct my_data {
40
my_data(int a, int b): a(a), b(b) {
41
42
}
43
44
int a;
45
int b;
46
};
47
48
struct root {
49
pmem::obj::persistent_ptr mdata;
50
};
51
52
int main(int argc, char *argv[]) {
53
auto pop = pmem::obj::pool::open("/daxfs/file", "tx");
Chapter 8 libpmemobj-Cpp: the adaptable language - C++ and persistent memory
Précédent

- 143/457

Suivant