CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
mutex.h
Go to the documentation of this file.
1
35
36#pragma once
37
38#include <cx/cx.h>
39#include <cx/meta/block.h>
40#include <cx/time/time.h>
41#include <cx/utils/macros.h>
42#include "aspin.h"
43#include "futex.h"
44
45#ifdef CX_LOCK_DEBUG
46#include <cx/log/log.h>
47#endif
48
49CX_C_BEGIN
50
55
60typedef struct Mutex {
61 Futex ftx;
62 AdaptiveSpin aspin;
64
65void _mutexInit(_Out_ Mutex* m, uint32 flags);
66
74#define mutexInit(m, ...) _mutexInit(m, opt_flags(__VA_ARGS__))
75
83_When_(return == true, _Acquires_nonreentrant_lock_(*m)) _When_(timeout == timeForever, _Acquires_nonreentrant_lock_(*m)) _When_(timeout != timeForever, _Must_inspect_result_) bool mutexTryAcquireTimeout(_Inout_ Mutex* m, int64 timeout);
84
91_Releases_nonreentrant_lock_(*m) bool mutexRelease(_Inout_ Mutex* m);
92
99_When_(return == true, _Acquires_nonreentrant_lock_(*m)) _Must_inspect_result_ _meta_inline bool mutexTryAcquire(_Inout_ Mutex* m)
100{
101 int32 curstate = atomicLoad(int32, &m->ftx.val, Relaxed);
102 if (curstate == 0 &&
103 atomicCompareExchange(int32, strong, &m->ftx.val, &curstate, 1, Acquire, Relaxed)) {
104 aspinRecordUncontended(&m->aspin);
105 return true;
106 }
107 return false;
108}
109
115_Acquires_nonreentrant_lock_(*m) _meta_inline void mutexAcquire(_Inout_ Mutex* m)
116{
118}
119
134#define withMutex(m) blkWrap (mutexAcquire(m), mutexRelease(m))
135
136#ifdef CX_LOCK_DEBUG
137// The indirection is what expands CX_LOCK_DEBUG to a level name before it is pasted. It used to
138// build the argument array here as well, which could not work: braces do not protect commas from
139// the preprocessor, so every argument past the first split the call.
140#define _logFmtMutexArgComp(level, fmt, ...) \
141 _logFmtArgs(level, LogDefault, LOG_SiteAlways, 0, fmt, __VA_ARGS__)
142_Acquires_nonreentrant_lock_(*m) static bool mutexLogAndAcquire(_Inout_ Mutex* m,
143 const char* name,
144 const char* filename, int line)
145{
146 _logFmtMutexArgComp(CX_LOCK_DEBUG,
147 _S"Locking mutex ${string} at ${string}:${int}",
148 stvar(string, (string)name),
149 stvar(string, (string)filename),
150 stvar(int32, line));
151 mutexAcquire(m);
152 return true;
153}
154
155#define mutexAcquire(m) mutexLogAndAcquire(m, #m, __FILE__, __LINE__)
156#endif
157
158#ifdef CX_LOCK_DEBUG
159_Releases_nonreentrant_lock_(*m) static bool mutexLogAndRelease(_Inout_ Mutex* m,
160 const char* name,
161 const char* filename, int line)
162{
163 _logFmtMutexArgComp(CX_LOCK_DEBUG,
164 _S"Releasing mutex ${string} at ${string}:${int}",
165 stvar(string, (string)name),
166 stvar(string, (string)filename),
167 stvar(int32, line));
168 return mutexRelease(m);
169}
170
171#define mutexRelease(m) mutexLogAndRelease(m, #m, __FILE__, __LINE__)
172#endif
173
179void mutexDestroy(_Pre_valid_ _Post_invalid_ Mutex* m);
180
181CX_C_END
182
184// end of thread_mutex group
Block wrapping macros for automatic resource management.
#define _S
Creates a static ASCII string literal (STR_LEN0, runtime strlen). Prefer _SL() on hot paths when targ...
Definition strliteral.h:91
#define stvar(typen, val)
Definition stvar.h:162
bool mutexTryAcquireTimeout(Mutex *m, int64 timeout)
void mutexAcquire(Mutex *m)
Definition mutex.h:115
void mutexDestroy(Mutex *m)
bool mutexTryAcquire(Mutex *m)
Definition mutex.h:99
MUTEX_Flags
Mutex initialization flags.
Definition mutex.h:52
bool mutexRelease(Mutex *m)
@ MUTEX_NoSpin
Disable adaptive spinning, use kernel futex immediately.
Definition mutex.h:53
#define timeForever
Maximum representable time value (approximately year 294,276 CE)
Definition time.h:15
Core logging system API.
Definition mutex.h:60
Futex ftx
Futex for kernel-level synchronization.
Definition mutex.h:61
AdaptiveSpin aspin
Adaptive spin state.
Definition mutex.h:62
Time manipulation and conversion functions.