diff options
author | Araq <rumpf_a@web.de> | 2014-06-03 08:25:42 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2014-06-03 08:25:42 +0200 |
commit | a4323b06b321b77ea36bf738efdfa481faf9822c (patch) | |
tree | 3b8a6bf7149fcc57b33319e18278b70eca3b44d9 /lib/pure/concurrency | |
parent | 7303c3292f42be78555f7a7241f0c46634557d37 (diff) | |
download | Nim-a4323b06b321b77ea36bf738efdfa481faf9822c.tar.gz |
barrier more efficient
Diffstat (limited to 'lib/pure/concurrency')
-rw-r--r-- | lib/pure/concurrency/threadpool.nim | 44 |
1 files changed, 25 insertions, 19 deletions
diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim index 22f00bc0d..92d5011f4 100644 --- a/lib/pure/concurrency/threadpool.nim +++ b/lib/pure/concurrency/threadpool.nim @@ -40,33 +40,39 @@ proc signal(cv: var CondVar) = release(cv.L) signal(cv.c) +const CacheLineSize = 32 # true for most archs + type - Barrier* {.compilerProc.} = object + Barrier {.compilerProc.} = object entered: int - cv: CondVar - cacheAlign: array[0..20, byte] # ensure 'left' is not on the same - # cache line as 'entered' + cv: CondVar # condvar takes 3 words at least + when sizeof(int) < 8: + cacheAlign: array[CacheLineSize-4*sizeof(int), byte] left: int + cacheAlign2: array[CacheLineSize-sizeof(int), byte] + interest: bool ## wether the master is interested in the "all done" event -proc barrierEnter*(b: ptr Barrier) {.compilerProc.} = - atomicInc b.entered +proc barrierEnter(b: ptr Barrier) {.compilerProc, inline.} = + ## due to the signaling between threads, it is ensured we are the only + ## one with access to 'entered' so we don't need 'atomicInc' here: + inc b.entered -proc barrierLeave*(b: ptr Barrier) {.compilerProc.} = +proc barrierLeave(b: ptr Barrier) {.compilerProc, inline.} = 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) + if b.interest and b.left == b.entered: signal(b.cv) -proc openBarrier*(b: ptr Barrier) {.compilerProc.} = +proc openBarrier(b: ptr Barrier) {.compilerProc, inline.} = b.entered = 0 - b.cv = createCondVar() - b.left = -1 - -proc closeBarrier*(b: ptr Barrier) {.compilerProc.} = - # signal interest in the "all done" event: - atomicInc b.left - while b.left != b.entered: await(b.cv) - destroyCondVar(b.cv) + b.left = 0 + b.interest = false + +proc closeBarrier(b: ptr Barrier) {.compilerProc.} = + if b.left != b.entered: + b.cv = createCondVar() + b.interest = true # XXX we really need to ensure no re-orderings are done + # by the C compiler here + while b.left != b.entered: await(b.cv) + destroyCondVar(b.cv) {.pop.} |