aboutsummaryrefslogtreecommitdiff
path: root/src/threading.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-01-03 15:26:47 +0000
committergingerBill <bill@gingerbill.org>2023-01-03 15:26:47 +0000
commitc7a704d345e9bda38da18807a1d7cd5bc5accc17 (patch)
tree230117068173a8052495272c2f2ed03a616c0c11 /src/threading.cpp
parent0fb3032b731b640a2d0d1d62b9f8dd548e224b0e (diff)
Use `RwMutex` for the `Scope`
Diffstat (limited to 'src/threading.cpp')
-rw-r--r--src/threading.cpp96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/threading.cpp b/src/threading.cpp
index 78943150e..27a17112e 100644
--- a/src/threading.cpp
+++ b/src/threading.cpp
@@ -8,10 +8,12 @@
struct BlockingMutex;
struct RecursiveMutex;
+struct RwMutex;
struct Semaphore;
struct Condition;
struct Thread;
struct ThreadPool;
+struct Parker;
#define THREAD_PROC(name) isize name(struct Thread *thread)
gb_internal THREAD_PROC(thread_pool_thread_proc);
@@ -56,6 +58,13 @@ gb_internal void mutex_lock (RecursiveMutex *m);
gb_internal bool mutex_try_lock(RecursiveMutex *m);
gb_internal void mutex_unlock (RecursiveMutex *m);
+gb_internal void rw_mutex_lock (RwMutex *m);
+gb_internal bool rw_mutex_try_lock (RwMutex *m);
+gb_internal void rw_mutex_unlock (RwMutex *m);
+gb_internal void rw_mutex_shared_lock (RwMutex *m);
+gb_internal bool rw_mutex_try_shared_lock(RwMutex *m);
+gb_internal void rw_mutex_shared_unlock (RwMutex *m);
+
gb_internal void semaphore_post (Semaphore *s, i32 count);
gb_internal void semaphore_wait (Semaphore *s);
gb_internal void semaphore_release(Semaphore *s) { semaphore_post(s, 1); }
@@ -65,6 +74,10 @@ gb_internal void condition_broadcast(Condition *c);
gb_internal void condition_signal(Condition *c);
gb_internal void condition_wait(Condition *c, BlockingMutex *m);
+gb_internal void park(Parker *p);
+gb_internal void unpark_one(Parker *p);
+gb_internal void unpark_all(Parker *p);
+
gb_internal u32 thread_current_id(void);
gb_internal void thread_init (ThreadPool *pool, Thread *t, isize idx);
@@ -205,6 +218,30 @@ gb_internal void semaphore_wait(Semaphore *s) {
gb_internal void condition_wait(Condition *c, BlockingMutex *m) {
SleepConditionVariableSRW(&c->cond, &m->srwlock, INFINITE, 0);
}
+
+ struct RwMutex {
+ SRWLOCK srwlock;
+ };
+
+ gb_internal void rw_mutex_lock(RwMutex *m) {
+ AcquireSRWLockExclusive(&m->srwlock);
+ }
+ gb_internal bool rw_mutex_try_lock(RwMutex *m) {
+ return !!TryAcquireSRWLockExclusive(&m->srwlock);
+ }
+ gb_internal void rw_mutex_unlock(RwMutex *m) {
+ ReleaseSRWLockExclusive(&m->srwlock);
+ }
+
+ gb_internal void rw_mutex_shared_lock(RwMutex *m) {
+ AcquireSRWLockShared(&m->srwlock);
+ }
+ gb_internal bool rw_mutex_try_shared_lock(RwMutex *m) {
+ return !!TryAcquireSRWLockShared(&m->srwlock);
+ }
+ gb_internal void rw_mutex_shared_unlock(RwMutex *m) {
+ ReleaseSRWLockShared(&m->srwlock);
+ }
#else
enum Internal_Mutex_State : i32 {
Internal_Mutex_State_Unlocked = 0,
@@ -306,8 +343,67 @@ gb_internal void semaphore_wait(Semaphore *s) {
futex_wait(&c->state(), state);
mutex_lock(m);
}
+
+ struct RwMutex {
+ // TODO(bill): make this a proper RW mutex
+ BlockingMutex mutex;
+ };
+
+ gb_internal void rw_mutex_lock(RwMutex *m) {
+ mutex_lock(&m->mutex);
+ }
+ gb_internal bool rw_mutex_try_lock(RwMutex *m) {
+ return mutex_try_lock(&m->mutex);
+ }
+ gb_internal void rw_mutex_unlock(RwMutex *m) {
+ mutex_unlock(&m->mutex);
+ }
+
+ gb_internal void rw_mutex_shared_lock(RwMutex *m) {
+ mutex_lock(&m->mutex);
+ }
+ gb_internal bool rw_mutex_try_shared_lock(RwMutex *m) {
+ return mutex_try_lock(&m->mutex);
+ }
+ gb_internal void rw_mutex_shared_unlock(RwMutex *m) {
+ mutex_unlock(&m->mutex);
+ }
#endif
+struct Parker {
+ Futex state;
+};
+enum ParkerState : u32 {
+ ParkerState_Empty = 0,
+ ParkerState_Notified = 1,
+ ParkerState_Parked = UINT32_MAX,
+};
+
+gb_internal void park(Parker *p) {
+ if (p->state.fetch_sub(1, std::memory_order_acquire) == ParkerState_Notified) {
+ return;
+ }
+ for (;;) {
+ futex_wait(&p->state, ParkerState_Parked);
+ i32 notified = ParkerState_Empty;
+ if (p->state.compare_exchange_strong(notified, ParkerState_Empty, std::memory_order_acquire, std::memory_order_acquire)) {
+ return;
+ }
+ }
+}
+
+gb_internal void unpark_one(Parker *p) {
+ if (p->state.exchange(ParkerState_Notified, std::memory_order_release) == ParkerState_Parked) {
+ futex_signal(&p->state);
+ }
+}
+
+gb_internal void unpark_all(Parker *p) {
+ if (p->state.exchange(ParkerState_Notified, std::memory_order_release) == ParkerState_Parked) {
+ futex_broadcast(&p->state);
+ }
+}
+
gb_internal u32 thread_current_id(void) {
u32 thread_id;