192
68 pop.close();
69 } catch (std::exception &e) {
70
std::cerr << e.what() << std::endl;
71 }
72 }
• Lines 37-45: We define two different data structures to store records
of integers. The first one is SoA – where we store integers in two
separate arrays. Line 44 shows a single array of pairs – AoS.
• Lines 56-59: We take advantage of the SoA layout by snapshotting the
entire array at once. Then we can safely modify each element.
• Lines 61-65: When using AoS, we are forced to snapshot data in every
iteration – elements we want to modify are not contiguous in memory.
Examples of data structures that use transactions are shown in the “Hash Table with
Transactions” and “Hash Table with Transactions and Selective Persistence” sections,
later in this chapter.
Copy-on-Write and Versioning
Another way to maintain consistency is the copy-on-write (CoW) technique. In this
approach, every modification creates a new version at a new location whenever you
want to modify some part of a persistent data structure. For example, a node in a linked
list can use the CoW approach as described in the following:
1. Create a copy of the element in the list. If a copy is dynamically
allocated in persistent memory, you should also save the pointer
in persistent memory to avoid a memory leak. If you fail to do
that and the application crashes after the allocation, then on the
application restart, newly allocated memory will be unreachable.
2. Modify the copy and persist the changes.
3. Atomically change the original element with the copy and persist
the changes, then free the original node if needed. After this
step successfully completes, the element is updated and is in a
consistent state. If a crash occurs before this step, the original
element is untouched.
Chapter 11 Designing Data struCtures for persistent MeMory
Précédent

- 216/457

Suivant