added a (maybe function) semaphore implementation
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 17 Oct 2021 21:21:10 +0000 (16:21 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 17 Oct 2021 21:21:10 +0000 (16:21 -0500)
core/sync/mutex.onyx
core/sync/semaphore.onyx [new file with mode: 0644]

index 4b8292b039053974af30fc0b315d47e0b3a08d7d..ecaf5518a3b230951c2444696cec443bba4dcb20 100644 (file)
@@ -2,6 +2,18 @@ package core.sync
 
 use package core.intrinsics.atomics
 
+// `lock` has two states: 0, and 1.
+//    0 means unlocked
+//    1 means locked
+//
+// To lock it:
+//    Try to store 1 if the value was already 0
+//    Otherwise, if it was already 1, wait until it goes to 0.
+//
+// To unlock it:
+//    Atomically set it to 0.
+//    Notify at most 1 other thread about this change.
+
 Mutex :: struct {
     lock  : i32;
     // owner : Thread_Id;
@@ -17,7 +29,7 @@ mutex_destroy :: (m: ^Mutex) {
 
 mutex_lock :: (m: ^Mutex) {
     while __atomic_cmpxchg(^m.lock, 0, 1) == 1 {
-        __atomic_wait(^m.lock, 0);
+        __atomic_wait(^m.lock, 1);
     }
 }
 
diff --git a/core/sync/semaphore.onyx b/core/sync/semaphore.onyx
new file mode 100644 (file)
index 0000000..7ecf5f4
--- /dev/null
@@ -0,0 +1,37 @@
+package core.sync
+
+use package core.intrinsics.atomics
+
+Semaphore :: struct {
+    mutex   : Mutex;
+    counter : i32;
+}
+
+semaphore_init :: (s: ^Semaphore, value: i32) {
+    s.counter = value;
+
+    mutex_init(^s.mutex);
+}
+
+semaphore_post :: (s: ^Semaphore) {
+    scoped_mutex(^s.mutex);
+    s.counter += 1;
+    __atomic_notify(^s.counter, maximum = 1);
+}
+
+semaphore_wait :: (s: ^Semaphore) {
+    while true {
+        mutex_lock(^s.mutex);
+        if s.counter > 0 {
+            s.counter -= 1;
+
+            mutex_unlock(^s.mutex);
+            return;
+
+        } else {
+            mutex_unlock(^s.mutex);
+
+            __atomic_wait(^s.counter, 0);
+        }
+    }
+}
\ No newline at end of file