Explorar o código

Add `wait_group_wait_with_timeout`; Allow `Sema` to be implemented as a `Wait_Group`

gingerBill %!s(int64=3) %!d(string=hai) anos
pai
achega
753acc6971
Modificáronse 2 ficheiros con 24 adicións e 48 borrados
  1. 20 0
      core/sync/sync2/extended.odin
  2. 4 48
      core/sync/sync2/sema_internal.odin

+ 20 - 0
core/sync/sync2/extended.odin

@@ -1,5 +1,7 @@
 package sync2
 
+import "core:time"
+
 // A Wait_Group waits for a collection of threads to finish
 //
 // A Wait_Group must not be copied after first use
@@ -45,6 +47,24 @@ wait_group_wait :: proc(wg: ^Wait_Group) {
 	}
 }
 
+wait_group_wait_with_timeout :: proc(wg: ^Wait_Group, duration: time.Duration) -> bool {
+	if duration <= 0 {
+		return false
+	}
+	mutex_lock(&wg.mutex)
+	defer mutex_unlock(&wg.mutex)
+
+	if wg.counter != 0 {
+		if !cond_wait_with_timeout(&wg.cond, &wg.mutex, duration) {
+			return false
+		}
+		if wg.counter != 0 {
+			panic("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait")
+		}
+	}
+	return true
+}
+
 
 
 // A barrier enabling multiple threads to synchronize the beginning of some computation

+ 4 - 48
core/sync/sync2/sema_internal.odin

@@ -55,62 +55,18 @@ when #config(ODIN_SYNC_SEMA_USE_FUTEX, true) {
 	}
 } else {
 	_Sema :: struct {
-		mutex: Mutex,
-		cond:  Cond,
-		count: i32,
+		wg: Wait_Group,
 	}
 
 	_sema_post :: proc(s: ^Sema, count := 1) {
-		mutex_lock(&s.impl.mutex)
-		defer mutex_unlock(&s.impl.mutex)
-		
-		s.impl.count += i32(count)
-		if count == 1 {
-			cond_signal(&s.impl.cond)
-		} else {
-			cond_broadcast(&s.impl.cond)
-		}
+		wait_group_add(&s.impl.wg, count)
 	}
 
 	_sema_wait :: proc(s: ^Sema) {
-		mutex_lock(&s.impl.mutex)
-		defer mutex_unlock(&s.impl.mutex)
-		
-		for s.impl.count == 0 {
-			cond_wait(&s.impl.cond, &s.impl.mutex)
-		}
-		
-		s.impl.count -= 1
-		if s.impl.count > 0 {
-			cond_signal(&s.impl.cond)
-		}
+		wait_group_wait(&s.impl.wg)
 	}
 
 	_sema_wait_with_timeout :: proc(s: ^Sema, duration: time.Duration) -> bool {
-		if duration <= 0 {
-			return false
-		}
-		
-		mutex_lock(&s.impl.mutex)
-		defer mutex_unlock(&s.impl.mutex)
-		
-		start := time.tick_now()
-		for s.impl.count == 0 {
-			remaining := duration - time.tick_since(start)
-			if remaining < 0 {
-				return false
-			}
-			
-			if !cond_wait_with_timeout(&s.impl.cond, &s.impl.mutex, remaining) {
-				return false
-			}
-		}
-		
-		s.impl.count -= 1
-		if s.impl.count > 0 {
-			cond_signal(&s.impl.cond)
-		}
-		
-		return true
+		return wait_group_wait_with_timeout(&s.impl.wg, duration)
 	}
 }