Browse Source

Add `atomic_cond_wait_with_timeout`

gingerBill 3 years ago
parent
commit
a1e8769cff
2 changed files with 35 additions and 3 deletions
  1. 34 0
      core/sync/sync2/primitives_atomic.odin
  2. 1 3
      core/sync/sync2/primitives_darwin.odin

+ 34 - 0
core/sync/sync2/primitives_atomic.odin

@@ -1,5 +1,7 @@
 package sync2
 package sync2
 
 
+import "core:time"
+
 Atomic_Mutex_State :: enum Futex {
 Atomic_Mutex_State :: enum Futex {
 	Unlocked = 0,
 	Unlocked = 0,
 	Locked   = 1,
 	Locked   = 1,
@@ -298,6 +300,21 @@ queue_item_wait :: proc(item: ^Queue_Item) {
 	}
 	}
 }
 }
 @(private="file")
 @(private="file")
+queue_item_wait_with_timeout :: proc(item: ^Queue_Item, duration: time.Duration) -> bool {
+	start := time.tick_now()
+	for atomic_load_acquire(&item.futex) == 0 {
+		remaining := duration - time.tick_since(start)
+		if remaining < 0 {
+			return false
+		}
+		if futex_wait_with_timeout(&item.futex, 0, remaining) == .Timed_Out {
+			return false
+		}
+		cpu_relax()
+	}
+	return true
+}
+@(private="file")
 queue_item_signal :: proc(item: ^Queue_Item) {
 queue_item_signal :: proc(item: ^Queue_Item) {
 	atomic_store_release(&item.futex, 1)
 	atomic_store_release(&item.futex, 1)
 	futex_wake_single(&item.futex)
 	futex_wake_single(&item.futex)
@@ -329,6 +346,23 @@ atomic_cond_wait :: proc(c: ^Atomic_Cond, m: ^Atomic_Mutex) {
 	atomic_mutex_lock(m)
 	atomic_mutex_lock(m)
 }
 }
 
 
+atomic_cond_wait_with_timeout :: proc(c: ^Atomic_Cond, m: ^Atomic_Mutex, duration: time.Duration) -> (ok: bool) {
+	waiter := &Queue_Item{}
+
+	atomic_mutex_lock(&c.queue_mutex)
+	waiter.next = c.queue_head
+	c.queue_head = waiter
+
+	atomic_store(&c.pending, true)
+	atomic_mutex_unlock(&c.queue_mutex)
+
+	atomic_mutex_unlock(m)
+	ok = queue_item_wait_with_timeout(waiter, duration)
+	atomic_mutex_lock(m)
+	return
+}
+
+
 atomic_cond_signal :: proc(c: ^Atomic_Cond) {
 atomic_cond_signal :: proc(c: ^Atomic_Cond) {
 	if !atomic_load(&c.pending) {
 	if !atomic_load(&c.pending) {
 		return
 		return

+ 1 - 3
core/sync/sync2/primitives_darwin.odin

@@ -45,9 +45,7 @@ _cond_wait :: proc(c: ^Cond, m: ^Mutex) {
 }
 }
 
 
 _cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, duration: time.Duration) -> bool {
 _cond_wait_with_timeout :: proc(c: ^Cond, m: ^Mutex, duration: time.Duration) -> bool {
-	// TODO(bill): _cond_wait_with_timeout for Darwin
-	atomic_cond_wait(&c.impl.cond, &m.impl.mutex)
-	return true
+	return atomic_cond_wait_with_timeout(&c.impl.cond, &m.impl.mutex, duration)
 }
 }
 
 
 _cond_signal :: proc(c: ^Cond) {
 _cond_signal :: proc(c: ^Cond) {