From 66741bc8ef82776b480713fcfc298f315bfa6530 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 7 Nov 2014 14:09:59 -0800 Subject: 258 - new channel helpers: empty? and full? --- mu.arc | 30 +++++++++++++++++++++ mu.arc.t | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 118 insertions(+), 4 deletions(-) diff --git a/mu.arc b/mu.arc index d9e96210..ba5b39d3 100644 --- a/mu.arc +++ b/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))) diff --git a/mu.arc.t b/mu.arc.t index 41513a33..1c18eeeb 100644 --- a/mu.arc.t +++ b/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. -- cgit 1.4.1-2-gfad0