Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
Threading.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "../Foundation/AlignedStorage.h"
5#include "../Foundation/Function.h"
6#include "../Foundation/Result.h"
7#include "Internal/Optional.h" // UniqueOptional
8
9namespace SC
10{
11struct Thread;
12struct ConditionVariable;
13struct Mutex;
14struct RWLock;
15struct Barrier;
16struct EventObject;
17struct Semaphore;
18} // namespace SC
19
22
25
31{
32 Mutex();
33 ~Mutex();
34
35 // Underlying OS primitives can't be copied or moved
36 Mutex(const Mutex&) = delete;
37 Mutex(Mutex&&) = delete;
38 Mutex& operator=(const Mutex&) = delete;
39 Mutex& operator=(Mutex&&) = delete;
40
41 void lock();
42 void unlock();
43
44 private:
45 friend struct ConditionVariable;
46#if SC_PLATFORM_APPLE
47 static constexpr int OpaqueMutexSize = 56 + sizeof(long);
48 static constexpr int OpaqueMutexAlignment = alignof(long);
49#elif SC_PLATFORM_WINDOWS
50 static constexpr int OpaqueMutexSize = 4 * sizeof(void*) + 2 * sizeof(long);
51 static constexpr int OpaqueMutexAlignment = alignof(void*);
52#elif SC_PLATFORM_EMSCRIPTEN
53 static constexpr int OpaqueMutexSize = sizeof(void*) * 6 + sizeof(long);
54 static constexpr int OpaqueMutexAlignment = alignof(long);
55#else
56 static constexpr int OpaqueMutexSize = sizeof(void*) * 6;
57 static constexpr int OpaqueMutexAlignment = alignof(long);
58#endif
59 // Wrap native mutex as opaque array of bytes
61 OpaqueMutex mutex;
62};
63
66{
69
70 // Underlying OS primitives can't be copied or moved
71 ConditionVariable(const ConditionVariable&) = delete;
73 ConditionVariable& operator=(const ConditionVariable&) = delete;
74 ConditionVariable& operator=(ConditionVariable&&) = delete;
75
76 void wait(Mutex& mutex);
77 void signal();
78 void broadcast();
79
80 private:
81#if SC_PLATFORM_APPLE
82 static constexpr int OpaqueCVSize = 40 + sizeof(long);
83 static constexpr int OpaqueCVAlignment = alignof(long);
84#elif SC_PLATFORM_WINDOWS
85 static constexpr int OpaqueCVSize = sizeof(void*);
86 static constexpr int OpaqueCVAlignment = alignof(void*);
87#elif SC_PLATFORM_EMSCRIPTEN
88 static constexpr int OpaqueCVSize = sizeof(void*) * 12;
89 static constexpr int OpaqueCVAlignment = alignof(long);
90#else
91 static constexpr int OpaqueCVSize = sizeof(void*) * 6;
92 static constexpr int OpaqueCVAlignment = alignof(long);
93#endif
94
95 // Wrap native condition variable as opaque array of bytes
98};
99
121{
122 Thread() = default;
123 ~Thread();
124
125 // Cannot be copied or moved (as it would require a dynamic allocation for the type erased Function)
126 Thread(Thread&&) = delete;
127 Thread& operator=(Thread&&) = delete;
128 Thread(const Thread&) = delete;
129 Thread& operator=(const Thread&) = delete;
130
134
137
140 Result start(Function<void(Thread&)>&& func);
141
145 void setThreadName(const native_char_t* name);
146
150
155
158 [[nodiscard]] bool wasStarted() const;
159
162 static void Sleep(uint32_t milliseconds);
163
164 private:
165 void setThreadNameInternal(const native_char_t* name);
166 struct Internal;
167 using OpaqueThread = AlignedStorage<sizeof(void*), alignof(void*)>;
168 UniqueOptional<OpaqueThread> thread;
169 Function<void(Thread&)> userFunction;
170};
171
177{
178 RWLock() = default;
179 ~RWLock() = default;
180
181 RWLock(const RWLock&) = delete;
182 RWLock(RWLock&&) = delete;
183 RWLock& operator=(const RWLock&) = delete;
184 RWLock& operator=(RWLock&&) = delete;
185
187 void lockRead();
188
191
193 void lockWrite();
194
197
198 private:
199 Mutex mutex;
200
201 ConditionVariable readersQ;
202 ConditionVariable writersQ;
203
204 int activeReaders = 0;
205 int waitingWriters = 0;
206 bool writerActive = false;
207};
208
214{
217 Barrier(uint32_t count) : threadCount(count) {}
218
220 void wait();
221
222 private:
223 const uint32_t threadCount;
224
225 uint32_t waitCount = 0;
226 uint32_t generation = 0;
227 Mutex mutex;
228
229 ConditionVariable condition;
230};
231
237{
238 bool autoReset = true;
239
241 void wait();
242
244 void signal();
245
246 private:
247 bool isSignaled = false;
248 Mutex mutex;
249
251};
252
258{
261 Semaphore(int initialCount = 0);
262
264 void acquire();
265
267 void release();
268
269 private:
270 int count;
271 Mutex mutex;
272
273 ConditionVariable condition;
274};
275
unsigned long long uint64_t
Platform independent (8) bytes unsigned int.
Definition PrimitiveTypes.h:42
unsigned int uint32_t
Platform independent (4) bytes unsigned int.
Definition PrimitiveTypes.h:38
char native_char_t
The native char for the platform (wchar_t (4 bytes) on Windows, char (1 byte) everywhere else )
Definition PrimitiveTypes.h:34
A synchronization point that blocks threads until the required number of threads have reached it.
Definition Threading.h:214
Barrier(uint32_t count)
Creates a barrier that waits for the specified number of threads.
Definition Threading.h:217
void wait()
Wait at the barrier until all threads have reached it.
A native OS condition variable.
Definition Threading.h:66
An automatically reset event object to synchronize two threads.
Definition Threading.h:237
void signal()
Unblocks another thread, waiting on EventObject::wait.
void wait()
Waits on a thread for EventObject::signal to be called from another thread.
Wraps function pointers, member functions and lambdas without ever allocating.
Definition Function.h:19
A native OS mutex to synchronize access to shared resources.
Definition Threading.h:31
A Read-Write lock that allows multiple concurrent readers but only one writer.
Definition Threading.h:177
void lockWrite()
Acquire a write lock. Only one writer can hold the lock, and no readers can hold it simultaneously.
void unlockWrite()
Release a previously acquired write lock.
void lockRead()
Acquire a read lock. Multiple readers can hold the lock concurrently.
void unlockRead()
Release a previously acquired read lock.
An ascii string used as boolean result. SC_TRY macro forwards errors to caller.
Definition Result.h:12
A semaphore synchronization primitive that maintains a count for resource management.
Definition Threading.h:258
void acquire()
Wait for a resource to become available.
void release()
Make a resource available.
Semaphore(int initialCount=0)
Creates a semaphore with an initial count.
A native OS thread.
Definition Threading.h:121
bool wasStarted() const
Check if thread has been started.
static void Sleep(uint32_t milliseconds)
Puts current thread to sleep.
Result start(Function< void(Thread &)> &&func)
Starts the new thread with given name and func.
void setThreadName(const native_char_t *name)
Sets current thread name ONLY if called from inside the thread.
Result detach()
Detaches the thread so that its resources are automatically released back to the system without Threa...
static uint64_t CurrentThreadID()
Returns thread id of the thread calling the function.
uint64_t threadID()
Returns thread id of this thread object (not current thread)
Result join()
Waits for thread to finish and releases its resources.