258 - new channel helpers: empty? and full?

This commit is contained in:
Kartik K. Agaram 2014-11-07 14:09:59 -08:00
parent 0a52288c41
commit 66741bc8ef
2 changed files with 118 additions and 4 deletions

30
mu.arc
View File

@ -602,6 +602,7 @@
(def sizeof (type)
(trace "sizeof" type)
(assert types*.type "sizeof: no such type @type")
(if (~or types*.type!record types*.type!array)
types*.type!size
types*.type!record
@ -715,6 +716,7 @@
(if (in op 'get 'get-address)
(with (basetype (typeinfo args.0)
field (v args.1))
(assert basetype "no such type @args.0")
(trace "cn0" "field-access " field)
; todo: need to rename args.0 as well?
(when (pos 'deref (metadata args.0))
@ -889,6 +891,34 @@
((watch boolean-address deref) <- copy (t literal))
(reply (result tagged-value) (chan channel)))
; An empty channel has first-empty and first-full both at the same value.
; 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)
(init-fn empty?
((default-scope scope-address) <- new (scope literal) (30 literal))
((chan channel) <- arg)
((full integer) <- get (chan channel) (first-full offset))
((free integer) <- get (chan channel) (first-free offset))
((result boolean) <- eq (full integer) (free integer))
(reply (result boolean)))
(init-fn full?
((default-scope scope-address) <- new (scope literal) (30 literal))
((chan channel) <- arg)
((full integer) <- get (chan channel) (first-full offset))
((curr integer) <- get (chan channel) (first-free offset))
((q tagged-value-array-address) <- get (chan channel) (circular-buffer offset))
((qlen integer) <- len (q tagged-value-array-address deref))
((curr integer) <- add (curr integer) (1 literal))
{ begin
((remaining? boolean) <- lt (curr integer) (qlen integer))
(break-if (remaining? boolean))
((curr integer) <- copy (0 literal))
}
((result boolean) <- eq (full integer) (curr integer))
(reply (result boolean)))
; drop all traces while processing above functions
(on-init
(= traces* (queue)))

View File

@ -147,6 +147,7 @@
; look for it. Everything outside 'add-fns' is just test-harness details.
(reset)
;? (set dump-trace*)
(new-trace "literal")
(add-fns
'((main
@ -1937,11 +1938,94 @@
(~is 0 memory*.5))
(prn "F - 'read' can wrap pointer back to start"))
; An empty channel has first-empty and first-full both at the same value.
; 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)
(reset)
(new-trace "channel-new-empty-not-full")
(add-fns
'((main
((1 channel-address) <- new-channel (3 literal))
((2 boolean) <- empty? (1 channel-address deref))
((3 boolean) <- full? (1 channel-address deref)))))
;? (set dump-trace*)
(run 'main)
;? (prn memory*)
(if (or (~is t memory*.2)
(~is nil memory*.3))
(prn "F - a new channel is always empty, never full"))
; TODO
(reset)
(new-trace "channel-write-not-empty")
(add-fns
'((main
((1 channel-address) <- new-channel (3 literal))
((2 integer-address) <- new (integer literal))
((2 integer-address deref) <- copy (34 literal))
((3 tagged-value-address) <- new-tagged-value (integer-address literal) (2 integer-address))
((1 channel-address deref) <- write (1 channel-address deref) (3 tagged-value-address deref))
((4 boolean) <- empty? (1 channel-address deref))
((5 boolean) <- full? (1 channel-address deref)))))
;? (set dump-trace*)
(run 'main)
;? (prn memory*)
(if (or (~is nil memory*.4)
(~is nil memory*.5))
(prn "F - a channel after writing is never empty"))
(reset)
(new-trace "channel-write-full")
(add-fns
'((main
((1 channel-address) <- new-channel (2 literal))
((2 integer-address) <- new (integer literal))
((2 integer-address deref) <- copy (34 literal))
((3 tagged-value-address) <- new-tagged-value (integer-address literal) (2 integer-address))
((1 channel-address deref) <- write (1 channel-address deref) (3 tagged-value-address deref))
((4 boolean) <- empty? (1 channel-address deref))
((5 boolean) <- full? (1 channel-address deref)))))
;? (set dump-trace*)
(run 'main)
;? (prn memory*)
(if (or (~is nil memory*.4)
(~is t memory*.5))
(prn "F - a channel after writing may be full"))
(reset)
(new-trace "channel-read-not-full")
(add-fns
'((main
((1 channel-address) <- new-channel (3 literal))
((2 integer-address) <- new (integer literal))
((2 integer-address deref) <- copy (34 literal))
((3 tagged-value-address) <- new-tagged-value (integer-address literal) (2 integer-address))
((1 channel-address deref) <- write (1 channel-address deref) (3 tagged-value-address deref))
((1 channel-address deref) <- write (1 channel-address deref) (3 tagged-value-address deref))
(_ (1 channel-address deref) <- read (1 channel-address deref))
((4 boolean) <- empty? (1 channel-address deref))
((5 boolean) <- full? (1 channel-address deref)))))
;? (set dump-trace*)
(run 'main)
;? (prn memory*)
(if (or (~is nil memory*.4)
(~is nil memory*.5))
(prn "F - a channel after reading is never full"))
(reset)
(new-trace "channel-read-empty")
(add-fns
'((main
((1 channel-address) <- new-channel (3 literal))
((2 integer-address) <- new (integer literal))
((2 integer-address deref) <- copy (34 literal))
((3 tagged-value-address) <- new-tagged-value (integer-address literal) (2 integer-address))
((1 channel-address deref) <- write (1 channel-address deref) (3 tagged-value-address deref))
(_ (1 channel-address deref) <- read (1 channel-address deref))
((4 boolean) <- empty? (1 channel-address deref))
((5 boolean) <- full? (1 channel-address deref)))))
;? (set dump-trace*)
(run 'main)
;? (prn memory*)
(if (or (~is t memory*.4)
(~is nil memory*.5))
(prn "F - a channel after reading may be empty"))
; We'd like to block routines when they write to a full channel or read from
; an empty channel.