about summary refs log tree commit diff stats
path: root/075channel.mu
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2017-06-20 09:12:03 -0700
committerKartik K. Agaram <vc@akkartik.com>2017-06-20 10:17:09 -0700
commit359586f0ee29f46f33decd33d0c55b8e4f052053 (patch)
tree39919134dc081acba42f63c300cc604c095ed9da /075channel.mu
parent9f67a02cbb7b2096a18274cca79d5b01be8de7e7 (diff)
downloadmu-359586f0ee29f46f33decd33d0c55b8e4f052053.tar.gz
3932
Some corrections and one bugfix to channels after reviewing their
implementation with Caleb Couch.
Diffstat (limited to '075channel.mu')
-rw-r--r--075channel.mu30
1 files changed, 25 insertions, 5 deletions
diff --git a/075channel.mu b/075channel.mu
index da5ca7e2..d9a252fd 100644
--- a/075channel.mu
+++ b/075channel.mu
@@ -32,8 +32,8 @@ container channel:_elem [
   first-full:num  # for write
   first-free:num  # for read
   # A circular buffer contains values from index first-full up to (but not
-  # including) index first-empty. The reader always modifies it at first-full,
-  # while the writer always modifies it at first-empty.
+  # including) index first-free. The reader always modifies it at first-full,
+  # while the writer always modifies it at first-free.
   data:&:@:_elem
 ]
 
@@ -63,6 +63,7 @@ def new-channel capacity:num -> in:&:source:_elem, out:&:sink:_elem [
   *out <- put *out, chan:offset, result
 ]
 
+# write a value to a channel
 def write out:&:sink:_elem, val:_elem -> out:&:sink:_elem [
   local-scope
   load-ingredients
@@ -108,6 +109,7 @@ def write out:&:sink:_elem, val:_elem -> out:&:sink:_elem [
   reset lock
 ]
 
+# read a value from a channel
 def read in:&:source:_elem -> result:_elem, eof?:bool, in:&:source:_elem [
   local-scope
   load-ingredients
@@ -166,6 +168,7 @@ def clear in:&:source:_elem -> in:&:source:_elem [
     empty?:bool <- channel-empty? chan
     break-if empty?
     _, _, in <- read in
+    loop
   }
 ]
 
@@ -301,6 +304,23 @@ scenario channel-read-not-full [
   ]
 ]
 
+scenario channel-clear [
+  local-scope
+  # create a channel with a few items
+  source:&:source:num, sink:&:sink:num <- new-channel 3/capacity
+  chan:&:channel:num <- get *sink, chan:offset
+  write sink, 30
+  write sink, 31
+  write sink, 32
+  run [
+    clear source
+    10:bool/raw <- channel-empty? chan
+  ]
+  memory-should-contain [
+    10 <- 1  # after the call to 'clear', the channel should be empty
+  ]
+]
+
 ## cancelling channels
 
 # every channel comes with a boolean signifying if it's been closed
@@ -346,7 +366,7 @@ after <channel-read-empty> [
 
 ## helpers
 
-# An empty channel has first-empty and first-full both at the same value.
+# An empty channel has first-free and first-full both at the same value.
 def channel-empty? chan:&:channel:_elem -> result:bool [
   local-scope
   load-ingredients
@@ -356,8 +376,8 @@ def channel-empty? chan:&:channel:_elem -> result:bool [
   result <- equal full, free
 ]
 
-# A full channel has first-empty just before first-full, wasting one slot.
-# (Other alternatives: https://en.wikipedia.org/wiki/Circular_buffer#Full_.2F_Empty_Buffer_Distinction)
+# A full channel has first-free just before first-full, wasting one slot.
+# (Other alternatives: https://www.snellman.net/blog/archive/2016-12-13-ring-buffers)
 def channel-full? chan:&:channel:_elem -> result:bool [
   local-scope
   load-ingredients