Expand description
The half-lock structure
We need a way to protect the structure with configured hooks ‒ a signal may happen in arbitrary thread and needs to read them while another thread might be manipulating the structure.
Under ordinary circumstances we would be happy to just use Mutex<HashMap<c_int, _>>
. However,
as we use it in the signal handler, we are severely limited in what we can or can’t use. So we
choose to implement kind of spin-look thing with atomics.
In the reader it is always simply locked and then unlocked, making sure it doesn’t disappear while in use.
The writer has a separate mutex (that prevents other writers; this is used outside of the signal handler), makes a copy of the data and swaps an atomic pointer to the data structure. But it waits until everything is unlocked (no signal handler has the old data) for dropping the old instance. There’s a generation trick to make sure that new signal locks another instance.
The downside is, this is an active spin lock at the writer end. However, we assume than:
- Signals are one time setup before we actually have threads. We just need to make sure we are safe even if this is not true.
- Signals are rare, happening at the same time as the write even rarer.
- Signals are short, as there is mostly nothing allowed inside them anyway.
- Our tool box is severely limited.
Therefore this is hopefully reasonable trade-off.
§Atomic orderings
The whole code uses SeqCst conservatively. Atomics are not used because of performance here and are the minor price around signals anyway. But the comments state which orderings should be enough in practice in case someone wants to get inspired (but do make your own check through them anyway).
Structs§
- Half
Lock 🔒 - Read
Guard 🔒 - Write
Guard 🔒