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{
11
14
17
22struct SC_COMPILER_EXPORT Mutex
23{
24 Mutex();
25 ~Mutex();
26
27 // Underlying OS primitives can't be copied or moved
28 Mutex(const Mutex&) = delete;
29 Mutex(Mutex&&) = delete;
30 Mutex& operator=(const Mutex&) = delete;
31 Mutex& operator=(Mutex&&) = delete;
32
33 void lock();
34 void unlock();
35
36 private:
37 friend struct ConditionVariable;
38#if SC_PLATFORM_APPLE
39 static constexpr int OpaqueMutexSize = 56 + sizeof(long);
40 static constexpr int OpaqueMutexAlignment = alignof(long);
41#elif SC_PLATFORM_WINDOWS
42 static constexpr int OpaqueMutexSize = 4 * sizeof(void*) + 2 * sizeof(long);
43 static constexpr int OpaqueMutexAlignment = alignof(void*);
44#elif SC_PLATFORM_EMSCRIPTEN
45 static constexpr int OpaqueMutexSize = sizeof(void*) * 6 + sizeof(long);
46 static constexpr int OpaqueMutexAlignment = alignof(long);
47#else
48 static constexpr int OpaqueMutexSize = sizeof(void*) * 6;
49 static constexpr int OpaqueMutexAlignment = alignof(long);
50#endif
51 // Wrap native mutex as opaque array of bytes
53 OpaqueMutex mutex;
54};
55
57struct SC_COMPILER_EXPORT ConditionVariable
58{
61
62 // Underlying OS primitives can't be copied or moved
63 ConditionVariable(const ConditionVariable&) = delete;
65 ConditionVariable& operator=(const ConditionVariable&) = delete;
66 ConditionVariable& operator=(ConditionVariable&&) = delete;
67
68 void wait(Mutex& mutex);
69 void signal();
70 void broadcast();
71
72 private:
73#if SC_PLATFORM_APPLE
74 static constexpr int OpaqueCVSize = 40 + sizeof(long);
75 static constexpr int OpaqueCVAlignment = alignof(long);
76#elif SC_PLATFORM_WINDOWS
77 static constexpr int OpaqueCVSize = sizeof(void*);
78 static constexpr int OpaqueCVAlignment = alignof(void*);
79#elif SC_PLATFORM_EMSCRIPTEN
80 static constexpr int OpaqueCVSize = sizeof(void*) * 12;
81 static constexpr int OpaqueCVAlignment = alignof(long);
82#else
83 static constexpr int OpaqueCVSize = sizeof(void*) * 6;
84 static constexpr int OpaqueCVAlignment = alignof(long);
85#endif
86
87 // Wrap native condition variable as opaque array of bytes
90};
91
112struct SC_COMPILER_EXPORT Thread
113{
114 Thread() = default;
115 ~Thread();
116
117 // Cannot be copied or moved (as it would require a dynamic allocation for the type erased Function)
118 Thread(Thread&&) = delete;
119 Thread& operator=(Thread&&) = delete;
120 Thread(const Thread&) = delete;
121 Thread& operator=(const Thread&) = delete;
122
126
129
132 Result start(Function<void(Thread&)>&& func);
133
137 void setThreadName(const native_char_t* name);
138
142
147
150 [[nodiscard]] bool wasStarted() const;
151
154 static void Sleep(uint32_t milliseconds);
155
156 private:
157 void setThreadNameInternal(const native_char_t* name);
158 struct Internal;
159 using OpaqueThread = AlignedStorage<sizeof(void*), alignof(void*)>;
160 UniqueOptional<OpaqueThread> thread;
161 Function<void(Thread&)> userFunction;
162};
163
168struct SC_COMPILER_EXPORT RWLock
169{
170 RWLock() = default;
171 ~RWLock() = default;
172
173 RWLock(const RWLock&) = delete;
174 RWLock(RWLock&&) = delete;
175 RWLock& operator=(const RWLock&) = delete;
176 RWLock& operator=(RWLock&&) = delete;
177
179 void lockRead();
180
183
185 void lockWrite();
186
189
190 private:
191 Mutex mutex;
192
193 ConditionVariable readersQ;
194 ConditionVariable writersQ;
195
196 int activeReaders = 0;
197 int waitingWriters = 0;
198 bool writerActive = false;
199};
200
205struct SC_COMPILER_EXPORT Barrier
206{
209 Barrier(uint32_t count) : threadCount(count) {}
210
212 void wait();
213
214 private:
215 const uint32_t threadCount;
216
217 uint32_t waitCount = 0;
218 uint32_t generation = 0;
219 Mutex mutex;
220
221 ConditionVariable condition;
222};
223
228struct SC_COMPILER_EXPORT EventObject
229{
230 bool autoReset = true;
231
233 void wait();
234
236 void signal();
237
238 private:
239 bool isSignaled = false;
240 Mutex mutex;
241
243};
244
249struct SC_COMPILER_EXPORT Semaphore
250{
253 Semaphore(int initialCount = 0);
254
256 void acquire();
257
259 void release();
260
261 private:
262 int count;
263 Mutex mutex;
264
265 ConditionVariable condition;
266};
267
269} // namespace SC
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
struct SC_COMPILER_EXPORT Function
Wraps function pointers, member functions and lambdas without ever allocating.
Definition Function.h:19
A synchronization point that blocks threads until the required number of threads have reached it.
Definition Threading.h:206
Barrier(uint32_t count)
Creates a barrier that waits for the specified number of threads.
Definition Threading.h:209
void wait()
Wait at the barrier until all threads have reached it.
A native OS condition variable.
Definition Threading.h:58
An automatically reset event object to synchronize two threads.
Definition Threading.h:229
void signal()
Unblocks another thread, waiting on EventObject::wait.
void wait()
Waits on a thread for EventObject::signal to be called from another thread.
A native OS mutex to synchronize access to shared resources.
Definition Threading.h:23
A Read-Write lock that allows multiple concurrent readers but only one writer.
Definition Threading.h:169
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:13
A semaphore synchronization primitive that maintains a count for resource management.
Definition Threading.h:250
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:113
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.