ObjFW  Diff

Differences From Artifact [b1091dda6a]:

To Artifact [31506d7dcf]:


25
26
27
28
29
30
31


32
33
34
35
36
37
38

#if !defined(OF_HAVE_THREADS) || \
    (!defined(OF_HAVE_PTHREADS) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS))
# error No mutexes available!
#endif

#import "macros.h"



#if defined(OF_HAVE_PTHREADS)
# include <pthread.h>
typedef pthread_mutex_t OFPlainMutex;
#elif defined(OF_WINDOWS)
# include <windows.h>
typedef CRITICAL_SECTION OFPlainMutex;







>
>







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

#if !defined(OF_HAVE_THREADS) || \
    (!defined(OF_HAVE_PTHREADS) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS))
# error No mutexes available!
#endif

#import "macros.h"

/** @file */

#if defined(OF_HAVE_PTHREADS)
# include <pthread.h>
typedef pthread_mutex_t OFPlainMutex;
#elif defined(OF_WINDOWS)
# include <windows.h>
typedef CRITICAL_SECTION OFPlainMutex;
64
65
66
67
68
69
70









71







72







73







74







75












76







77







78







79







80
81
82
83
84
85
86




87
88
89
90
91
92
93
94
95
96






97
98
99
100
101
102
103
104
105
106
107
108
109






110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126






127
128
129
130
131
132
133
	OFTLSKey count;
} OFPlainRecursiveMutex;
#endif

#ifdef __cplusplus
extern "C" {
#endif









extern int OFPlainMutexNew(OFPlainMutex *mutex);







extern int OFPlainMutexLock(OFPlainMutex *mutex);







extern int OFPlainMutexTryLock(OFPlainMutex *mutex);







extern int OFPlainMutexUnlock(OFPlainMutex *mutex);







extern int OFPlainMutexFree(OFPlainMutex *mutex);












extern int OFPlainRecursiveMutexNew(OFPlainRecursiveMutex *rmutex);







extern int OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex);







extern int OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex);







extern int OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex);







extern int OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex);
#ifdef __cplusplus
}
#endif

/* Spinlocks are inlined for performance. */





static OF_INLINE void
OFYieldThread(void)
{
#if defined(OF_HAVE_SCHED_YIELD)
	sched_yield();
#elif defined(OF_WINDOWS)
	Sleep(0);
#endif
}







static OF_INLINE int
OFSpinlockNew(OFSpinlock *spinlock)
{
#if defined(OF_HAVE_ATOMIC_OPS)
	*spinlock = 0;
	return 0;
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return pthread_spin_init(spinlock, 0);
#else
	return OFPlainMutexNew(spinlock);
#endif
}







static OF_INLINE int
OFSpinlockTryLock(OFSpinlock *spinlock)
{
#if defined(OF_HAVE_ATOMIC_OPS)
	if (OFAtomicIntCompareAndSwap(spinlock, 0, 1)) {
		OFAcquireMemoryBarrier();
		return 0;
	}

	return EBUSY;
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return pthread_spin_trylock(spinlock);
#else
	return OFPlainMutexTryLock(spinlock);
#endif
}







static OF_INLINE int
OFSpinlockLock(OFSpinlock *spinlock)
{
#if defined(OF_HAVE_ATOMIC_OPS)
	size_t i;

	for (i = 0; i < 10; i++)







>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>

>
>
>
>
>
>
>

>
>
>
>
>
>
>

>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>

>
>
>
>
>
>
>

>
>
>
>
>
>
>

>
>
>
>
>
>
>







>
>
>
>










>
>
>
>
>
>













>
>
>
>
>
>

















>
>
>
>
>
>







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
	OFTLSKey count;
} OFPlainRecursiveMutex;
#endif

#ifdef __cplusplus
extern "C" {
#endif
/**
 * @brief Creates a new plain mutex.
 *
 * A plain mutex is similar to an @ref OFMutex, but does not use exceptions and
 * is just a lightweight wrapper around the system's mutex implementation.
 *
 * @param mutex A pointer to the mutex to create
 * @return 0 on success, or an error number from `<errno.h>` on error
 */
extern int OFPlainMutexNew(OFPlainMutex *mutex);

/**
 * @brief Locks the specified mutex.
 *
 * @param mutex A pointer to the mutex to lock
 * @return 0 on success, or an error number from `<errno.h>` on error
 */
extern int OFPlainMutexLock(OFPlainMutex *mutex);

/**
 * @brief Tries to lock the specified mutex without blocking.
 *
 * @param mutex A pointer to the mutex to try to lock
 * @return 0 on success, or an error number from `<errno.h>` on error
 */
extern int OFPlainMutexTryLock(OFPlainMutex *mutex);

/**
 * @brief Unlocks the specified mutex.
 *
 * @param mutex A pointer to the mutex to unlock
 * @return 0 on success, or an error number from `<errno.h>` on error
 */
extern int OFPlainMutexUnlock(OFPlainMutex *mutex);

/**
 * @brief Destroys the specified mutex
 *
 * @param mutex A pointer to the mutex to destruct
 * @return 0 on success, or an error number from `<errno.h>` on error
 */
extern int OFPlainMutexFree(OFPlainMutex *mutex);

/**
 * @brief Creates a new plain recursive mutex.
 *
 * A plain recursive mutex is similar to an @ref OFRecursiveMutex, but does not
 * use exceptions and is just a lightweight wrapper around the system's
 * recursive mutex implementation (or lacking that, a simple implementation of
 * recursive mutexes via regular mutexes).
 *
 * @param rmutex A pointer to the recursive mutex to create
 * @return 0 on success, or an error number from `<errno.h>` on error
 */
extern int OFPlainRecursiveMutexNew(OFPlainRecursiveMutex *rmutex);

/**
 * @brief Locks the specified recursive mutex.
 *
 * @param rmutex A pointer to the recursive mutex to lock
 * @return 0 on success, or an error number from `<errno.h>` on error
 */
extern int OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex);

/**
 * @brief Tries to lock the specified recursive mutex without blocking.
 *
 * @param rmutex A pointer to the recursive mutex to try to lock
 * @return 0 on success, or an error number from `<errno.h>` on error
 */
extern int OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex);

/**
 * @brief Unlocks the specified recursive mutex.
 *
 * @param rmutex A pointer to the recursive mutex to unlock
 * @return 0 on success, or an error number from `<errno.h>` on error
 */
extern int OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex);

/**
 * @brief Destroys the specified recursive mutex
 *
 * @param rmutex A pointer to the recursive mutex to destruct
 * @return 0 on success, or an error number from `<errno.h>` on error
 */
extern int OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex);
#ifdef __cplusplus
}
#endif

/* Spinlocks are inlined for performance. */

/**
 * @brief Yield the current thread, indicating to the OS that another thread
 *	  should execute instead.
 */
static OF_INLINE void
OFYieldThread(void)
{
#if defined(OF_HAVE_SCHED_YIELD)
	sched_yield();
#elif defined(OF_WINDOWS)
	Sleep(0);
#endif
}

/**
 * @brief Creates a new spinlock.
 *
 * @param spinlock A pointer to the spinlock to create
 * @return 0 on success, or an error number from `<errno.h>` on error
 */
static OF_INLINE int
OFSpinlockNew(OFSpinlock *spinlock)
{
#if defined(OF_HAVE_ATOMIC_OPS)
	*spinlock = 0;
	return 0;
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return pthread_spin_init(spinlock, 0);
#else
	return OFPlainMutexNew(spinlock);
#endif
}

/**
 * @brief Tries to lock a spinlock.
 *
 * @param spinlock A pointer to the spinlock to try to lock
 * @return 0 on success, or an error number from `<errno.h>` on error
 */
static OF_INLINE int
OFSpinlockTryLock(OFSpinlock *spinlock)
{
#if defined(OF_HAVE_ATOMIC_OPS)
	if (OFAtomicIntCompareAndSwap(spinlock, 0, 1)) {
		OFAcquireMemoryBarrier();
		return 0;
	}

	return EBUSY;
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return pthread_spin_trylock(spinlock);
#else
	return OFPlainMutexTryLock(spinlock);
#endif
}

/**
 * @brief Locks a spinlock.
 *
 * @param spinlock A pointer to the spinlock to lock
 * @return 0 on success, or an error number from `<errno.h>` on error
 */
static OF_INLINE int
OFSpinlockLock(OFSpinlock *spinlock)
{
#if defined(OF_HAVE_ATOMIC_OPS)
	size_t i;

	for (i = 0; i < 10; i++)
141
142
143
144
145
146
147






148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163






164
165
166
167
168
169
170
171
172
173
174
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return pthread_spin_lock(spinlock);
#else
	return OFPlainMutexLock(spinlock);
#endif
}







static OF_INLINE int
OFSpinlockUnlock(OFSpinlock *spinlock)
{
#if defined(OF_HAVE_ATOMIC_OPS)
	bool ret = OFAtomicIntCompareAndSwap(spinlock, 1, 0);

	OFReleaseMemoryBarrier();

	return (ret ? 0 : EINVAL);
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return pthread_spin_unlock(spinlock);
#else
	return OFPlainMutexUnlock(spinlock);
#endif
}







static OF_INLINE int
OFSpinlockFree(OFSpinlock *spinlock)
{
#if defined(OF_HAVE_ATOMIC_OPS)
	return 0;
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return pthread_spin_destroy(spinlock);
#else
	return OFPlainMutexFree(spinlock);
#endif
}







>
>
>
>
>
>
















>
>
>
>
>
>











242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return pthread_spin_lock(spinlock);
#else
	return OFPlainMutexLock(spinlock);
#endif
}

/**
 * @brief Unlocks a spinlock.
 *
 * @param spinlock A pointer to the spinlock to unlock
 * @return 0 on success, or an error number from `<errno.h>` on error
 */
static OF_INLINE int
OFSpinlockUnlock(OFSpinlock *spinlock)
{
#if defined(OF_HAVE_ATOMIC_OPS)
	bool ret = OFAtomicIntCompareAndSwap(spinlock, 1, 0);

	OFReleaseMemoryBarrier();

	return (ret ? 0 : EINVAL);
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return pthread_spin_unlock(spinlock);
#else
	return OFPlainMutexUnlock(spinlock);
#endif
}

/**
 * @brief Destroys a spinlock.
 *
 * @param spinlock A pointer to the spinlock to destroy
 * @return 0 on success, or an error number from `<errno.h>` on error
 */
static OF_INLINE int
OFSpinlockFree(OFSpinlock *spinlock)
{
#if defined(OF_HAVE_ATOMIC_OPS)
	return 0;
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return pthread_spin_destroy(spinlock);
#else
	return OFPlainMutexFree(spinlock);
#endif
}