Ah, so when you wrote

Therefore, the beginning of
txn2
must happen-before the end oftxn1
.
then you meant the first operation on txn2
must happen-before the last operation on txn1
?
I think I understand now. (Please let me know if I got it wrong.)

Personally, I've often had success applying the heuristic where C library authors will never violate an implicit API assumption if violating it would require far more code than satisfying it. […] Thus, if we're already assuming that
MDB_txn *
pointers are unique, then it doesn't feel like much of a stretch to assume that they act like exclusive&mut
pointers, where the end of the old lifetime and the start of the new lifetime are synchronized, so that all other operations can be unsynchronized.
So in practice it actually boils down to whether we can assume that MDB_txn *
pointers are unique. While the LMDB API doesn't guarantee it (and in theory, a write transaction could have the same address as an arbitrary read transaction), I understand that it may be reasonable to assume it nonetheless.
Concluding (getting back to the subject of this thread), the Mutex<bool>
could – in this particular case – probably be replaced with an AtomicBool
using Relaxed
loads and stores. However, it requires some extra assumptions being true in regard LMDB behaving reasonably (which is not explicitly documented in the specification, and which might be similar with many other C APIs).
Replacing the Mutex<Bool>
with an atomic that uses simple loads and stores with SeqCst
still requires these extra assumptions to be true. So using SeqCst
makes no sense (here), which also matches what @farnz quoted in the other thread:
IMO,
SeqCst
atomics are more of a code smell thanArc<Mutex<bool>>
- withArc<Mutex<bool>>
, I know you've not thought about it, and you've just gone for the most obvious implementation that works, while withSeqCst
, I have to look at all accesses to the atomic to determine whether you're doing something deeply subtle and clever, or whether you've just chosenSeqCst
because you weren't thinking it through.To quote Mara Bos's excellent book on Rust Atomics and Locks:
While it might seem like the easiest memory ordering to reason about,
SeqCst
ordering is almost never necessary in practice.
Seeing this from the other side: If a Mutex<bool>
was necessary in this case, the solution to replace it with atomics is really complex and requires a lot of thinking and reasoning, and it doesn't result in simple stores and loads from an atomic.