about summary refs log tree commit diff stats
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
parent9f67a02cbb7b2096a18274cca79d5b01be8de7e7 (diff)
downloadmu-359586f0ee29f46f33decd33d0c55b8e4f052053.tar.gz
3932
Some corrections and one bugfix to channels after reviewing their
implementation with Caleb Couch.
-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
/* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
(function init-counter [
  (default-space:space-address <- new space:literal 30:literal)
  (n:integer <- next-input)
  (reply default-space:space-address)
 ])

(function increment-counter [
  (default-space:space-address <- new space:literal 30:literal)
  (0:space-address/names:init-counter <- next-input)  ; setup outer space; it *must* come from 'init-counter'
  (x:integer <- next-input)
  (n:integer/space:1 <- add n:integer/space:1 x:integer)
  (reply n:integer/space:1)
 ])

(function main [
  (default-space:space-address <- new space:literal 30:literal)
  ; counter A
  (a:space-address <- init-counter 34:literal)
  ; counter B
  (b:space-address <- init-counter 23:literal)
  ; increment both by 2 but in different ways
  (increment-counter a:space-address 1:literal)
  (bres:integer <- increment-counter b:space-address 2:literal)
  (ares:integer <- increment-counter a:space-address 1:literal)
  ; check results
  ($print (("Contents of counters a: " literal)))
  (print-integer nil:literal/terminal ares:integer)
  ($print ((" b: " literal)))
  (print-integer nil:literal/terminal bres:integer)
  ($print (("\n" literal)))
 ])

; compare http://www.paulgraham.com/accgen.html