Correctly implementing a spinlock in Modern C++

This page summarizes the projects mentioned and recommended in the original post on news.ycombinator.com

Our great sponsors
  • InfluxDB - Power Real-Time Data Analytics at Scale
  • WorkOS - The modern identity platform for B2B SaaS
  • SaaSHub - Software Alternatives and Reviews
  • Disruptor

    High Performance Inter-Thread Messaging Library

  • It's easy to fall into traps! I edited my original comment with a link to https://lmax-exchange.github.io/disruptor/ which has all the details on avoiding the pitfalls you mention.

    As to your specific concern, I think you should be able to preallocate a large buffer of objects that you want to share. In other words, the allocations only need to happen infrequently.

    The idea of going from "ringbuffer" to "multithreaded lock-free memory pool" is throwing up warning signals. It's true that you do need to be allocating memory, but the memory can be allocated by a thread (lock free), and then the slot is claimed and pointer written (still lock free). But there's nothing special about this process -- just allocate some memory, and stick it into the slot.

    The ringbuffer is the thing that handles the coordination.

    Is there a reason more complexity is justified? (More complexity might entirely be justified, and I just haven't had that experience.)

  • sync

  • Your reasoning is correct. Also, if it makes you sleep better :-), here's the boost implementation of a spinlock:

    https://github.com/boostorg/sync/blob/dfdf317f63d26fb40c703b...

    It has been written by an expert in lockfree programming (Tim Blechmann)

  • InfluxDB

    Power Real-Time Data Analytics at Scale. Get real-time insights from all types of time series data with InfluxDB. Ingest, query, and analyze billions of data points in real-time with unbounded cardinality.

    InfluxDB logo
  • multiversion-concurrency-control

    Implementation of multiversion concurrency control, Raft, Left Right concurrency Hashmaps and a multi consumer multi producer Ringbuffer, concurrent and parallel load-balanced loops, parallel actors implementation in Main.java, Actor2.java and a parallel interpreter

  • Multithreading sure is complicated.

    I'm currently playing with multithreading right now. I'm implementing snapshot isolation multiversion concurrency control.

    In theory you can avoid locks (except for data structure locks) by creating a copy of the data you want to write and detect conflicts at read and commit time. Set the read timestamp of a piece of data to the transaction timestamp (timestamps are just monotonically increasing numbers) that reads it. If someone with a higher transaction timestamp comes along, they abort and restart because someone got in before them.

    At the moment I have something that mostly works but occasionally executes a duplicate. I'm trying to eradicate the last source of bugs but as with anything parallel, it's complicated due to the interleavings.

    My test case is to spin up 100 threads, with each thread trying to increment a number. The end numbers should be 101 and 102. If there was a data race, then the numbers will be lower.

    https://github.com/samsquire/multiversion-concurrency-contro...

  • Multithreading sure is complicated.

    I'm currently playing with multithreading right now. I'm implementing snapshot isolation multiversion concurrency control.

    In theory you can avoid locks (except for data structure locks) by creating a copy of the data you want to write and detect conflicts at read and commit time. Set the read timestamp of a piece of data to the transaction timestamp (timestamps are just monotonically increasing numbers) that reads it. If someone with a higher transaction timestamp comes along, they abort and restart because someone got in before them.

    At the moment I have something that mostly works but occasionally executes a duplicate. I'm trying to eradicate the last source of bugs but as with anything parallel, it's complicated due to the interleavings.

    My test case is to spin up 100 threads, with each thread trying to increment a number. The end numbers should be 101 and 102. If there was a data race, then the numbers will be lower.

    https://github.com/samsquire/multiversion-concurrency-contro...

  • abseil-cpp

    Abseil Common Libraries (C++)

  • For a real battle-tested combination of spinlock and futex, see https://github.com/abseil/abseil-cpp/blob/master/absl/synchr...

  • supercollider

    An audio server, programming language, and IDE for sound synthesis and algorithmic composition.

  • MPMCQueue.h

    A bounded multi-producer multi-consumer concurrent queue written in C++11

  • You can align and pad each ring buffer slot to the cache line size. Example https://github.com/rigtorp/MPMCQueue/blob/master/include/rig...

  • WorkOS

    The modern identity platform for B2B SaaS. The APIs are flexible and easy-to-use, supporting authentication, user identity, and complex enterprise features like SSO and SCIM provisioning.

    WorkOS logo
NOTE: The number of mentions on this list indicates mentions on common posts plus user suggested alternatives. Hence, a higher number means a more popular project.

Suggest a related project

Related posts