258 - new channel helpers: empty? and full?
This commit is contained in:
parent
0a52288c41
commit
66741bc8ef
30
mu.arc
30
mu.arc
|
@ -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)))
|
||||
|
|
92
mu.arc.t
92
mu.arc.t
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue