|
JH-Toolkit v1.4.1
An engineering-oriented C++20 toolkit with duck-typed concepts, static design, async coroutines, and semantic containers โ header-only, RTTI-free, and concurrency-friendly.
|
Cross-platform named process-wide mutex primitive. More...
#include <jh/synchronous/ipc/process_mutex.h>
Public Member Functions | |
| process_mutex (const process_mutex &)=delete | |
| Deleted copy constructor. | |
| process_mutex & | operator= (const process_mutex &)=delete |
| Deleted copy assignment. | |
| process_mutex (process_mutex &&)=delete | |
| Deleted move constructor. | |
| process_mutex & | operator= (process_mutex &&)=delete |
| Deleted move assignment. | |
| void | lock () |
| Acquire the lock (blocking). | |
| bool | try_lock () |
| Try acquire without blocking. | |
| template<typename Rep, typename Period> | |
| bool | try_lock_for (const std::chrono::duration< Rep, Period > &d) |
| Attempt to acquire the lock, waiting for a maximum duration. | |
| template<typename Clock, typename Duration> | |
| bool | try_lock_until (const std::chrono::time_point< Clock, Duration > &tp) |
| Attempt to acquire the lock until an absolute time point. | |
| void | unlock () |
| Release the lock. | |
Static Public Member Functions | |
| static constexpr const char * | name () noexcept |
| Get OS-visible name. | |
| static process_mutex & | instance () |
| Singleton instance. | |
| static void | unlink () |
| Remove the semaphore name from the namespace (POSIX only). | |
| static void | unlink ()=delete |
| Disabled if HighPriv == false. Non-privileged mutexes cannot call unlink(). | |
Cross-platform named process-wide mutex primitive.
jh::sync::ipc::process_mutex is a low-level inter-process synchronization primitive that mirrors the behavior of std::timed_mutex, extended to operate across process boundaries via OS-level named semaphores. Each unique template literal S defines a globally visible named mutex.
std::timed_mutex: std::lock_guard, std::unique_lock, or equivalent user-defined wrappers. try_lock(), try_lock_for(), and try_lock_until() for timed acquisition. Cross-platform behavior
sem_open(), sem_wait(), and sem_post(). CreateSemaphore() and WaitForSingleObject(). unlock() without owning the mutex, or calling it multiple times, is undefined behavior. lock() twice without an intervening unlock() causes deadlock. Use RAII-style management whenever possible:
This ensures exception safety and correct pairing of lock()/unlock().
| S | Bare name string (letters, digits, dot, dash, underscore). |
| HighPriv | If true, exposes unlink() for POSIX. |
|
inline |
Acquire the lock (blocking).
Blocks the calling thread or process until the mutex becomes available. Once acquired, the caller obtains exclusive ownership of the process-wide synchronization primitive.
This mutex is non-recursive. Calling lock() twice from the same thread or process without a corresponding unlock() causes a self-deadlock, identical to the behavior of std::timed_mutex.
lock() call must eventually be paired with unlock(). When using process_mutex within a lexical scope, prefer RAII-style management with std::lock_guard or an equivalent wrapper to ensure exception-safe unlock.
| std::runtime_error | if the underlying system call fails unexpectedly. |
|
inline |
Attempt to acquire the lock, waiting for a maximum duration.
On Windows, this maps to WaitForSingleObject with a bounded timeout. On POSIX systems with the Realtime Extension (POSIX.1b) (e.g. Linux/glibc), this maps to sem_timedwait. On pure POSIX systems without the extension (e.g. Darwin, BSD), timed waiting is emulated with sem_trywait + exponential backoff sleep, which approximates the same semantics while avoiding busy spinning.
| Rep | Representation type of duration. |
| Period | Period type of duration. |
| d | Duration to wait. |
| std::runtime_error | if the underlying system call fails unexpectedly. |
try_lock_until for details.
|
inline |
Attempt to acquire the lock until an absolute time point.
Windows uses WaitForSingleObject with a computed relative timeout. POSIX with the Realtime Extension (POSIX.1b) (e.g. Linux/glibc) uses sem_timedwait with an absolute timespec. Pure POSIX systems without the extension (e.g. Darwin, BSD) emulate timed waiting via sem_trywait + exponential backoff sleep, preserving observable semantics (success/timeout) without excessive CPU usage.
| Clock | Clock type. |
| Duration | Duration type. |
| tp | Absolute time point at which the attempt should time out. |
| std::runtime_error | if the underlying system call fails unexpectedly. |
|
inlinestatic |
Remove the semaphore name from the namespace (POSIX only).
sem_unlink() with the internally constructed name. sem_close(). errno == ENOENT): the call is silently ignored. No exception is thrown. sem_unlink() fails for any other reason (e.g. permissions, resource errors), an exception is thrown. This operation is explicitly idempotent: calling unlink() multiple times is safe. Once the semaphore is removed, subsequent calls are treated as no-ops.
On Windows / MSYS2, there is no unlink concept. Named semaphores are automatically destroyed by the OS when the last handle is closed.
|
inline |
Release the lock.
Releases ownership of the process-wide mutex. This operation must only be called by a participant that currently holds the lock; calling unlock() without prior ownership or invoking it multiple times consecutively constitutes undefined behavior.
ReleaseSemaphore() from a thread that does not own the lock may raise a runtime error or terminate the process. unlock(). thread_local flags or process-scoped state) depending on usage scope. | std::runtime_error | if the underlying system call fails unexpectedly. |