Listing 3 shows the actions on the data blocks. For each
data block, we track the current version number and pointers
to the normal and speculative buffers. Non-speculative reads
and writes to a data block directly access the pointer and
incur little overhead. Speculative reads track the pointer
and version number of data block being accessed. Speculative writes create a private buffer for the current speculation
phase. Upon completion of a task’s write, the speculative
pointer is updated to forward this buffer for subsequent use
in the same speculation phase. While each speculative writer
gets a separate version to write to, the versioning scheme
only tracks the latest speculative version to be supplied to
any speculative readers.