diff options
Diffstat (limited to '072channel.mu')
-rw-r--r-- | 072channel.mu | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/072channel.mu b/072channel.mu index e1d6f805..7af7353e 100644 --- a/072channel.mu +++ b/072channel.mu @@ -61,6 +61,10 @@ def write out:address:sink:_elem, val:_elem -> out:address:sink:_elem [ local-scope load-ingredients chan:address:channel:_elem <- get *out, chan:offset + <channel-write-initial> + # BUG: delete next 2 lines after enabling the tangle directives below + closed?:boolean <- get *chan, closed?:offset + reply-if closed? { # block if chan is full full:boolean <- channel-full? chan @@ -94,6 +98,10 @@ def read in:address:source:_elem -> result:_elem, in:address:source:_elem [ # block if chan is empty empty?:boolean <- channel-empty? chan break-unless empty? + <channel-read-empty> + # BUG: delete next 2 lines after enabling the tangle directives below + closed?:boolean <- get *chan, closed?:offset + reply-if closed?, 0 # hack, will only work for scalar _elem; we need a method to clear arbitrary types free-address:location <- get-location *chan, first-free:offset wait-for-location free-address } @@ -250,6 +258,47 @@ scenario channel-read-not-full [ ] ] +## cancelling channels + +# every channel comes with a boolean signifying if it's been closed +# initially this boolean is false +# BUG: can't yet include type ingredients when extending containers +container channel [ + closed?:boolean +] + +# a channel can be closed from either the source or the sink +# both threads can modify it, but they can only set it, so this is a benign race +def close x:address:source:_elem -> x:address:source:_elem [ + local-scope + load-ingredients + chan:address:channel:_elem <- get *x, chan:offset + *chan <- put *chan, closed?:offset, 1/true +] +def close x:address:sink:_elem -> x:address:sink:_elem [ + local-scope + load-ingredients + chan:address:channel:_elem <- get *x, chan:offset + *chan <- put *chan, closed?:offset, 1/true +] + +# once a channel is closed from one side, no further operations are expected from that side +# if a channel is closed for reading, +# no further writes will be let through +# if a channel is closed for writing, +# future reads continue until the channel empties, +# then the channel is also closed for reading +# BUG: tangle directives don't work for some reason +#? after <channel-write-initial> [ +#? closed?:boolean <- get *chan, closed?:offset +#? reply-if closed? +#? ] +#? +#? after <channel-read-empty> [ +#? closed?:boolean <- get *chan, closed?:offset +#? reply-if closed? +#? ] + ## helpers # An empty channel has first-empty and first-full both at the same value. @@ -337,6 +386,11 @@ def buffer-lines in:address:source:character, buffered-out:address:sink:characte i <- add i, 1 loop } + { + break-unless eof? + buffered-out <- close buffered-out + reply + } loop } ] |