Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Transactional memory


Meshing operations demand guarantees for coordinated access across sets of variables. They may also be composed of multiple steps that should not be interrupted, or where intermediate mesh state may be invalid.

EdgeCutSteps
Edge cut operation with detailed steps.

For example, an edge cut in a triangular mesh is defined by the insertion of a vertex on an existing edge, before the creation of two new edges that cut across the original adjacent triangles. After the first vertex insertion, and before both edges creation, the mesh actually contains quadrangular cells. This is a state that should not be visible to other threads, nor should it be a final state.

Needs

In order to guarantee validity, we must ensure that these intermediate, incorrect states aren’t used by another thread to compute an erroneous result, i.e., that all changes made in a thread appear at once to others. To obtain our final system, we worked incrementally on a synchronization policy choice.

Rust’s ownership semantics require us to add synchronization mechanism to our structure if we want to use it in concurrent contexts. Using primitives such as atomics and mutexes would be enough to get programs to compile, but it would respectively yield an incorrect or impractical implementation:

  • Atomics give guarantees on instructions interleaving for a single given variable, these guarantees cannot be extended to a set of accesses across different variables.
  • Mutexes (and similar locks, e.g. RWLocks) can be used to implement greater synchronization coordination: for example, we can write an operation that does not progress until all of the used data is locked. However, locks are error-prone, have very poor composability. Issues that come with those grow along the number of locks used.

We detail how these usual mechanisms fail to provide the guarantees we need in one of our paper.

Software Transactional Memory

We choose to use Software Transactional Memory (STM) to handle high-level synchronization of the structure. Unlike locks, STM has great composability and allows users of the crate to easily define pseudo-atomic segments in their own algorithms.

EdgeCutSTM
Edge cut operation with detailed steps.

Exposing an API that allows users to handle synchronization also means that the implementation isn’t bound to a given parallelization framework. Instead of relying on predefinite parallel routines (e.g. a provided parallel_for on given cells), the structure can be used to implement existing algorithms regardless of their approach (data-oriented, task-based, …).