Separating Mechanism from Policy in STM - Sheng, Yaodong; Hassan, Ahmed; Spear, Michael (2023 32nd International Conference on Parallel Architectures and Compilation Techniques (PACT), 2023)
When designing concurrent data structures (CDSs), it can feel like programmers must choose between performance and convenience. On one hand, Software Transactional Memory (STM) is easy, because it allows programmers to simply mark regions of sequential code as requiring atomicity, and then the compiler ensures that no races manifest. However, this can easily lead to false conflicts that hinder scalability. On the other hand, programmers can craft custom lock-based or non-blocking protocols for operating on the CDS. This approach increases scalability, but is hard to get right. For lock-based optimistic data structures, we identify a compelling design point that effectively unifies the two approaches. The key idea is to employ the systems concept of "separation of policy and mechanism". This allows different operations to use the same transactional synchronization mechanism in different ways, on the same data structure, at the same time. That is, some operations can access the CDS via STM, while others use custom synchronization. We define exoTM as a synchronization mechanism extracted from a popular STM. We then introduce a high-performance exoTM-based multi-word compare-and-swap policy (STMCAS) for creating CDSs. STMCAS can checkpoint and resume read-only operations, and can run concurrently with an exoTM-based STM policy. This allows programmers to create CDSs by starting with STM and then incrementally optimizing with STMCAS until the desired performance is reached. Our experiments find that the low-level mechanisms are fast: our STMCAS-based data structures usually outperform lock-based and lock-free CDSs, at roughly the same level of effort. Furthermore, for complex CDSs (e.g., red/black trees), we can mix STMCAS and STM to keep complicated operations (re-balancing) simple while using STMCAS to optimize the common case (read-only traversal).