From a4ad640df16f3018682965ffbd83ecff7a6e460c Mon Sep 17 00:00:00 2001 From: Andy Davidoff Date: Thu, 23 Jul 2020 21:18:06 -0400 Subject: [PATCH] 0.0.5: signals, wait, semaphores --- README.md | 4 ++-- cps.nimble | 3 ++- cps/eventqueue.nim | 27 +++++++++++++++++++++++---- cps/semaphore.nim | 2 ++ docs/cps.html | 2 +- docs/cps/environment.html | 2 +- docs/theindex.html | 2 +- tests/tsignal.nim | 18 ++++++++++++++++++ tests/tsignal.nim.cfg | 5 +++++ 9 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 tests/tsignal.nim create mode 100644 tests/tsignal.nim.cfg diff --git a/README.md b/README.md index 99df8f32..ca2a9630 100644 --- a/README.md +++ b/README.md @@ -36,8 +36,8 @@ Key primitives and their implementation status, in order of priority: - [x] sleep - [x] yield - [x] discard -- [ ] signal -- [ ] wait +- [x] signal +- [x] wait - [ ] I/O - [ ] fork - [ ] thread diff --git a/cps.nimble b/cps.nimble index 4d39ad3d..be7e94e5 100644 --- a/cps.nimble +++ b/cps.nimble @@ -1,4 +1,4 @@ -version = "0.0.4" +version = "0.0.5" author = "disruptek" description = "continuation-passing style" license = "MIT" @@ -25,3 +25,4 @@ task test, "run tests for travis": execTest("tests/test.nim") execTest("tests/tock.nim") execTest("tests/tyield.nim") + execTest("tests/tsignal.nim") diff --git a/cps/eventqueue.nim b/cps/eventqueue.nim index b4088cf7..cf698525 100644 --- a/cps/eventqueue.nim +++ b/cps/eventqueue.nim @@ -144,6 +144,14 @@ proc len*(eq: EventQueue): int = ## The number of pending continuations. result = len(eq.goto) + len(eq.yields) + len(eq.pending) +proc `[]=`(eq: var EventQueue; s: var Semaphore; id: Id) = + ## put a semaphore into the queue with its registration + assert id != invalidId + assert id != wakeupId + assert not s.isReady + assert s.id.Id != invalidId + eq.pending[s] = id + proc `[]=`(eq: var EventQueue; id: Id; cont: Cont) = ## put a continuation into the queue according to its registration assert id != invalidId @@ -320,9 +328,9 @@ template signalImpl(s: Semaphore; body: untyped): untyped = wakeUp() proc cpsSignal*(s: var Semaphore): Cont {.cpsMagic.} = - ## signal the given semaphore, causing the first waiting continuation + ## Signal the given semaphore, causing the first waiting continuation ## to be queued for execution in the dispatcher; control remains in - ## the calling procedure + ## the calling procedure. result = c signal s withReady s: @@ -331,9 +339,9 @@ proc cpsSignal*(s: var Semaphore): Cont {.cpsMagic.} = discard proc cpsSignalAll*(s: var Semaphore): Cont {.cpsMagic.} = - ## signal the given semaphore, causing all waiting continuations + ## Signal the given semaphore, causing all waiting continuations ## to be queued for execution in the dispatcher; control remains in - ## the calling procedure + ## the calling procedure. result = c signal s if s.isReady: @@ -341,3 +349,14 @@ proc cpsSignalAll*(s: var Semaphore): Cont {.cpsMagic.} = while true: signalImpl s: break + +proc cpsWait*(s: var Semaphore): Cont {.cpsMagic.} = + ## Queue the current continuation pending readiness of the given + ## Semaphore `s`. + let id = nextId() + if s.isReady: + addLast(eq.yields, c) + wakeUp() + else: + eq[s] = id + eq[id] = c diff --git a/cps/semaphore.nim b/cps/semaphore.nim index 1a904d76..25be2e7c 100644 --- a/cps/semaphore.nim +++ b/cps/semaphore.nim @@ -8,6 +8,8 @@ type cond: Cond count: int +proc id*(s: Semaphore): int = s.id + proc hash*(s: Semaphore): Hash = result = s.id.Hash diff --git a/docs/cps.html b/docs/cps.html index a69c9e25..492c5e78 100644 --- a/docs/cps.html +++ b/docs/cps.html @@ -147,7 +147,7 @@

Macros

diff --git a/docs/cps/environment.html b/docs/cps/environment.html index aa3c2852..69a29d58 100644 --- a/docs/cps/environment.html +++ b/docs/cps/environment.html @@ -446,7 +446,7 @@

Templates

diff --git a/docs/theindex.html b/docs/theindex.html index 9e7e602c..4f08f443 100644 --- a/docs/theindex.html +++ b/docs/theindex.html @@ -223,7 +223,7 @@

Index

diff --git a/tests/tsignal.nim b/tests/tsignal.nim new file mode 100644 index 00000000..052760ca --- /dev/null +++ b/tests/tsignal.nim @@ -0,0 +1,18 @@ +import cps +import cps/eventqueue + +var sem = newSemaphore() +var success = false + +proc tick(ms: int): Cont {.cps.} = + cpsSleep ms + cpsSignal(sem) + +proc tock(): Cont {.cps.} = + cpsWait sem + success = true + +trampoline tick(10) +trampoline tock() + +run() diff --git a/tests/tsignal.nim.cfg b/tests/tsignal.nim.cfg new file mode 100644 index 00000000..f9f78b32 --- /dev/null +++ b/tests/tsignal.nim.cfg @@ -0,0 +1,5 @@ +--path="$config/.." +--threads:on +--define:threadsafe +--gc:arc +--define:cpsDebug