📁 Module: <jh/concurrency>
📦 Namespace: jh::conc
📍 Location: jh/concurrent/
📅 Version: 1.4.x (2025)
👤 Author: JeongHan-Bae <[email protected]>
jh::conc is the collection of concurrency-aware containers that keep synchronization inside each helper, letting
callers think in terms of resources (objects, keys, handles) rather than mutexes.
| Helper | Role |
|---|---|
occ_box<T> |
OCC-wrapped mutable state with wait-free readers and atomic copy-and-replace commits. |
flat_pool<Key, Value> / resource_pool<Key, Value> |
Contiguous key-driven pool for copyable/movable entries, exposing reference-counted handles. |
pointer_pool<T> / observe_pool<T> |
Weak-observed pools for pointer-stable, immutable data (the latter auto-deduces hash/equality). |
<jh/concurrency> aggregates every <jh/concurrent/*.h> helper into jh::conc. When you only need the alias-based
pools, include <jh/pool> so that jh::observe_pool/jh::resource_pool sit directly under jh::.
| Component | Header | Status | Description |
|---|---|---|---|
occ_box<T> |
<jh/concurrent/occ_box.h> |
✅ Stable | OCC container with optimistic reads, copy-on-write writes, and optional multi-box transactions. |
flat_pool<Key, Value> |
<jh/concurrent/flat_pool.h> |
✅ Stable | Key-based, contiguous pool exposing reference-counted handles, validator guards, and health metrics. |
pointer_pool<T, Hash, Eq> |
<jh/concurrent/pointer_pool.h> |
✅ Stable | Weak-pointer observer for immutable heap objects that must stay at fixed addresses. |
observe_pool<T> |
<jh/concurrent/observe_pool.h> |
✅ Stable | Duck-typed alias of pointer_pool that derives hash/equality from jh::hash<T>/ADL. |
resource_pool<Key, Value, Alloc> |
<jh/concurrent/resource_pool.h> |
✅ Stable | Simplified alias of flat_pool keyed by jh::hash<Key>, plus resource_pool_set<Key>. |
- Design goal: expose deterministic, lock-conscious containers where the surface API mirrors the managed resource rather than lock choreography.
- Entry points:
<jh/concurrency>delivers the rawjh::conchelpers;<jh/pool>re-exports the alias-based pools forjh::namespace convenience. - Caveat: when
jh::hash<T>cannot be deduced (e.g., types insidestdsuch asstd::variantthat forbid registeringstd::hash, ADLhash, or memberhash()), instantiate the rawjh::conc::*_pooltemplate with explicitHash/Eqfunctors, because the auto-deduction path has no hook into closed namespaces. - Multi-commit:
occ_boxoptionally enables multi-box transactions viaJH_OCC_ENABLE_MULTI_COMMIT(default1), placing multi-write commits ahead of single writers and readers.
📁 Module: <jh/pool>
📦 Namespace: jh
📍 Location: jh/concurrent/
<jh/pool> re-exports alias-based pools (observe_pool, resource_pool, etc.) directly under jh::.
These helpers are engineered around POSIX-style behavioral assumptions.
As of 1.4.x, Windows is treated as a compatibility platform, not a fully supported concurrency baseline for the
entire jh/pool module.
We introduced:
std::atomic_thread_fence(std::memory_order_seq_cst);around shared_mutex boundaries (via posix_smtx_*_lock).
This is the strongest ordering primitive available in ISO C++ at the language level.
However, it does not fully close the visibility gaps observed under:
- MinGW toolchains (MinGW-w64 / MinGW-clang)
- Windows runtimes (MSVCRT / UCRT)
- Interaction with OS-level primitives (e.g., SRWLock)
The behavior remains data-race-free (DRF) at the algorithmic level.
The instability arises from environmental constraints beyond the abstract C++ model.
Note:
On Windows, inserting
std::atomic_thread_fence(std::memory_order_seq_cst);
around shared_mutex boundaries measurably improves practical stability under contention.
It raises the threshold at which race-like symptoms manifest and delays instability in stress scenarios.
However, it cannot fully eliminate the underlying visibility gaps nor guarantee POSIX-level behavioral equivalence.
std::atomic_thread_fence can only constrain memory operations:
- Emitted by the current compiler
- Within the C++ abstract machine
- Visible in user-space generated code
It cannot:
- Control hidden synchronization inside system DLLs
- Strengthen ordering inside kernel-implemented locks
- Inject barriers into opaque runtime components
On Windows, primitives such as SRWLock are implemented inside system libraries (e.g., ntdll.dll).
If their internal memory ordering is optimized without full fences, user-inserted seq_cst cannot retroactively enforce
stronger guarantees.
The fence does not cross the ABI boundary.
Atomic operations guarantee:
- Atomicity — operations are indivisible.
- Ordering (within abstract machine) — relative sequencing.
They do not guarantee:
- Immediate global visibility across CPU cores.
- Hardware-level total ordering.
Modern CPUs use:
- Store buffers
- Cache-coherence protocols (e.g., MESI)
- Speculative execution
Even with seq_cst, there can be a physical delay between:
- Atomic write completion on CPU A
- Cache-line propagation to CPU B
If the Windows lock implementation does not enforce a bus-lock–grade synchronization boundary, extremely high-frequency contention may expose transient visibility windows.
This is a hardware-level constraint, not a C++ bug.
In the MinGW + UCRT/MSVCRT environment:
- The compiler may assume system calls imply sufficient ordering.
- The runtime may assume atomic operations are independently ordered.
std::shared_ptr(atomic refcount) andstd::shared_mutex(system lock) may not form a strongly coupled ordering chain at the machine-code level.
This weak cross-domain coupling can expose rare race-like symptoms under stress.
Once std::memory_order_seq_cst is insufficient, only two paths remain:
- Insert hardware-specific instructions (
MFENCE,LOCKprefixes, inline assembly). - Accept that the environment cannot provide POSIX-level closure.
Option 1 destroys portability and maintainability.
Option 2 is engineering reality.
If the strongest ISO C++ ordering primitive cannot bridge the gap, the issue is systemic, not algorithmic.
-
jh/poolimplementations remain algorithmically DRF. -
POSIX platforms (macOS, Linux GCC ≥13) define the reference behavior.
-
On Windows:
- API availability is guaranteed.
- Single-threaded or low-pressure multi-threaded usage is recommended.
- Full POSIX-equivalent global ordering is not guaranteed.
The inserted fences:
- Raise the instability threshold.
- Delay manifestation under contention.
- Improve convergence in practice.
They:
- Do not eliminate hardware-level reordering.
- Do not establish a true global total order.
This is a boundary where software cannot defeat hardware and platform policy.
Accordingly, the entire <jh/pool> module does not provide full Windows concurrency support.
| Resource | Link |
|---|---|
| 🏠 Back to README | |
📘 occ_box<T> Reference |
|
📗 flat_pool<Key, Value> Reference |
|
📙 pointer_pool<T> Reference |
|
📘 observe_pool<T> Reference |
|
📗 resource_pool Reference |