summary refs log tree commit diff stats
path: root/lib/pure/concurrency
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2014-06-02 19:03:01 +0200
committerAraq <rumpf_a@web.de>2014-06-02 19:03:01 +0200
commitfbadbb399ec8a3d01195d4b50f7f73d1e9e5d31b (patch)
tree98feff70ef00b8a4759fcc6adc1ae7838e107fdb /lib/pure/concurrency
parentb78173788d1f5e45091c31039e82960187db1277 (diff)
downloadNim-fbadbb399ec8a3d01195d4b50f7f73d1e9e5d31b.tar.gz
hopefully faster barrier implementation
Diffstat (limited to 'lib/pure/concurrency')
-rw-r--r--lib/pure/concurrency/threadpool.nim20
1 files changed, 14 insertions, 6 deletions
diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim
index 3a7693791..22f00bc0d 100644
--- a/lib/pure/concurrency/threadpool.nim
+++ b/lib/pure/concurrency/threadpool.nim
@@ -42,22 +42,30 @@ proc signal(cv: var CondVar) =
 
 type
   Barrier* {.compilerProc.} = object
-    counter: int
+    entered: int
     cv: CondVar
+    cacheAlign: array[0..20, byte] # ensure 'left' is not on the same
+                                   # cache line as 'entered'
+    left: int
 
 proc barrierEnter*(b: ptr Barrier) {.compilerProc.} =
-  atomicInc b.counter
+  atomicInc b.entered
 
 proc barrierLeave*(b: ptr Barrier) {.compilerProc.} =
-  atomicDec b.counter
-  if b.counter <= 0: signal(b.cv)
+  atomicInc b.left
+  # these can only be equal if 'closeBarrier' already signaled its interest
+  # in this event:
+  if b.left == b.entered: signal(b.cv)
 
 proc openBarrier*(b: ptr Barrier) {.compilerProc.} =
-  b.counter = 0
+  b.entered = 0
   b.cv = createCondVar()
+  b.left = -1
 
 proc closeBarrier*(b: ptr Barrier) {.compilerProc.} =
-  while b.counter > 0: await(b.cv)
+  # signal interest in the "all done" event:
+  atomicInc b.left
+  while b.left != b.entered: await(b.cv)
   destroyCondVar(b.cv)
 
 {.pop.}