130
56
node->next = nullptr;
57
58
if (head == nullptr) {
59
head = tail = node;
60
} else {
61
tail->next = node;
62
tail = node;
63
}
64
});
65
}
All the modifiers methods must be aware on which persistent memory pool they
should operate on. For a single memory pool, this is trivial, but if the application
memory maps files from different file systems, we need to keep track of which pool has
what data. We introduce an additional argument of type pmem::obj::pool_base to solve
this problem. Inside the method definition, we are wrapping the code with a transaction
by using a C++ lambda expression, [&], to guarantee atomicity and consistency of
modifications. Instead of allocating a new node on the stack, we call pmem::obj::make_
persistent<>() to transactionally allocate it on persistent memory.
Listing 8-9 shows the modification of the pop() method.
Listing 8-9. A persistent queue implementation – a persistent pop() method
67
int
68
pop(pmem::obj::pool_base &pop)
69
{
70
int value;
71
pmem::obj::transaction::run(pop, [&]{
72
if (head == nullptr)
73
throw std::out_of_range("no elements");
74
75
auto head_ptr = head;
76
value = head->value;
77
78
head = head->next;
79
pmem::obj::delete_persistent(head_ptr);
80
Chapter 8 libpmemobj-Cpp: the adaptable language - C++ and persistent memory
56
node->next = nullptr;
57
58
if (head == nullptr) {
59
head = tail = node;
60
} else {
61
tail->next = node;
62
tail = node;
63
}
64
});
65
}
All the modifiers methods must be aware on which persistent memory pool they
should operate on. For a single memory pool, this is trivial, but if the application
memory maps files from different file systems, we need to keep track of which pool has
what data. We introduce an additional argument of type pmem::obj::pool_base to solve
this problem. Inside the method definition, we are wrapping the code with a transaction
by using a C++ lambda expression, [&], to guarantee atomicity and consistency of
modifications. Instead of allocating a new node on the stack, we call pmem::obj::make_
persistent<>() to transactionally allocate it on persistent memory.
Listing 8-9 shows the modification of the pop() method.
Listing 8-9. A persistent queue implementation – a persistent pop() method
67
int
68
pop(pmem::obj::pool_base &pop)
69
{
70
int value;
71
pmem::obj::transaction::run(pop, [&]{
72
if (head == nullptr)
73
throw std::out_of_range("no elements");
74
75
auto head_ptr = head;
76
value = head->value;
77
78
head = head->next;
79
pmem::obj::delete_persistent
80
Chapter 8 libpmemobj-Cpp: the adaptable language - C++ and persistent memory
