Skip to content

Commit

Permalink
Merge pull request #41 from konsumlamm/waitgroups
Browse files Browse the repository at this point in the history
Improve `waitgroups`
  • Loading branch information
Araq authored Sep 8, 2023
2 parents b692590 + d53f56b commit bcc2849
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 8 deletions.
42 changes: 42 additions & 0 deletions tests/twaitgroups.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import threading/waitgroups

block basic:
var wg = createWaitGroup()
wg.enter(10)
for _ in 1..10:
wg.leave()
wg.wait()

block multiple_threads:
var data: array[10, int]
var wg = createWaitGroup()

proc worker(i: int) =
data[i] = 42
wg.leave()

var threads: array[10, Thread[int]]
wg.enter(10)
for i in 0..<10:
createThread(threads[i], worker, i)

wg.wait()
for x in data:
doAssert x == 42

joinThreads(threads)

block multiple_waits:
var wg = createWaitGroup()
wg.enter(1)

proc worker() =
wg.wait()

var threads: array[10, Thread[void]]
for i in 0..<10:
createThread(threads[i], worker)

wg.leave()

joinThreads(threads)
39 changes: 31 additions & 8 deletions threading/waitgroups.nim
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,32 @@

## Wait groups for Nim.

runnableExamples:

var data: array[10, int]
var wg = createWaitGroup()

proc worker(i: int) =
data[i] = 42
wg.leave()

var threads: array[10, Thread[int]]
wg.enter(10)
for i in 0..<10:
createThread(threads[i], worker, i)

wg.wait()
for x in data:
assert x == 42

joinThreads(threads)


import std / [locks]

type
WaitGroup* = object ## \
## A WaitGroup is an synchronization object that can be used to `wait` until
WaitGroup* = object
## A `WaitGroup` is a synchronization object that can be used to `wait` until
## all workers have completed.
c: Cond
L: Lock
Expand All @@ -36,19 +57,21 @@ proc createWaitGroup*(): WaitGroup =
initCond(result.c)
initLock(result.L)

proc enter*(b: var WaitGroup; delta = 1) {.inline.} =
## Tells the WaitGroup that one or more workers (the `delta` parameter says
## how many) "entered" which means to increase the counter that counts how
proc enter*(b: var WaitGroup; delta: Natural = 1) {.inline.} =
## Tells the `WaitGroup` that one or more workers (the `delta` parameter says
## how many) "entered", which means to increase the counter that counts how
## many workers to wait for.
acquire(b.L)
inc b.runningTasks, delta
release(b.L)

proc leave*(b: var WaitGroup) {.inline.} =
## Tells the WaitGroup that one worker has finished its task.
## Tells the `WaitGroup` that one worker has finished its task.
acquire(b.L)
dec b.runningTasks
signal(b.c)
if b.runningTasks > 0:
dec b.runningTasks
if b.runningTasks == 0:
broadcast(b.c)
release(b.L)

proc wait*(b: var WaitGroup) =
Expand Down

0 comments on commit bcc2849

Please sign in to comment.