Wanted: a portable mutex and atomic refcount
upb needs to have some lightweight thread-aware behavior. I’m leaving most synchronization up to users (individual messages will not be thread-safe), but there are a few central structures I need to make thread-safe and reference-counted.
I need only the tiniest bit of functionality:
- a portable mutex.
- a portable atomic_t that lets me atomic_inc() and atomic_dec().
We’re talking “lives in one single header” small. The mutex would just be wrappers around existing mutex implementations (pthreads, windows, etc), and since those routines typically take care of any memory barriers you need to safely read/mutate the shared state, I wouldn’t have to worry about that.
The atomic type would have to be hand-coded and architecture-specific, since most threading libraries don’t provide one. The reason for providing this would be reference-counting. If you are reference-counting an immutable structure, then you don’t need to worry about memory barriers to ensure the consistency of that structure; if you’re reference-counting a mutable structure, then you’ll need to protect the mutable state with mutexes and acquire the mutex before freeing anything.
The library (er, header file) should also support compiling everything to nothing if NO_THREAD_SAFETY is defined as a preprocessor symbol.
Yes, that all sounds good. Tiny yet functional. I’ll be writing this very soon unless something exactly like what I’ve described happens to already exist.
One of my projects, the Open Portable Atomics (or sometimes OpenPA or OPA) would probably fulfill at least half of your requirements. We support a half-dozen or so (depending on how you count it) architectures right now with plans to add more incrementally. We would also welcome contributions if you have a platform that you need it to work on. The license is very permissive, basically MIT-style, do whatever you want with it.
https://trac.mcs.anl.gov/projects/openpa/
It of course provides _more_ functionality than you need, but not excessively so. So you might count it out on the basis of “not tiny enough for Josh’s taste”
It definitely doesn’t live in one header file, we typically use one header for each platform. At the very least you could use it as the starting point for your crazy minimalist implementation, since writing this sort of thing is *very* error prone.
One of the goals for the library is simplicity of use, which means that we made design decisions to minimize the amount of feature testing that you need to do as the consumer of the API. This is in stark contrast to the libatomic_ops project which attempts to provide atomics for most/all fixed width types on the platform in full combination with the various memory barrier types (last time I looked at it, anyway).
Do you really want it to compile to nothing if you specify NO_THREAD_SAFETY or do you want thread-unsafe operations to occur instead? I can see use cases for both, although probably the thread-unsafe version is what you want in most cases.
We have a layer in MPICH2 that wraps pthreads, windows, and solaris mutex APIs, although it is extremely ugly and there’s no way that you would be able to sensibly disentangle it from the library (that’s all legacy code that I didn’t write). That’s something that would probably be worth implementing in OPA some day, although I doubt I’ll get around to it any time soon. Getting into the business of wrapping the threading library is a whole separate can of portability worms than writing atomic assembly inlines.
Mail me if you want more detailed info about OPA.