about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-01-10 13:49:16 -0800
committerKartik K. Agaram <vc@akkartik.com>2015-01-10 13:49:16 -0800
commitea0d661bb77ca3a844ff7c7268cd5a9b3266265c (patch)
treed68c3c67405e3125f5284cc5a4d958ced7a358bd
parent9c2ed239561c069beba0953616ddab15ac21265b (diff)
downloadmu-ea0d661bb77ca3a844ff7c7268cd5a9b3266265c.tar.gz
529 - 'sleep' can now wait for a routine to complete
-rw-r--r--channel.mu7
-rw-r--r--mu.arc5
-rw-r--r--mu.arc.t26
3 files changed, 35 insertions, 3 deletions
diff --git a/channel.mu b/channel.mu
index 8e03cdc2..4fa6adaf 100644
--- a/channel.mu
+++ b/channel.mu
@@ -41,7 +41,8 @@
 (function main [
   (chan:channel-address <- init-channel 3:literal)
   ; create two background 'routines' that communicate by a channel
-  (fork consumer:fn nil:literal/globals nil:literal/limit chan:channel-address)
-  (fork producer:fn nil:literal/globals nil:literal/limit chan:channel-address)
-  (sleep for-some-cycles:literal 2000:literal)  ; wait for forked routines to effect the transfer
+  (routine1:integer <- fork consumer:fn nil:literal/globals nil:literal/limit chan:channel-address)
+  (routine2:integer <- fork producer:fn nil:literal/globals nil:literal/limit chan:channel-address)
+  (sleep until-routine-done:literal routine1:integer)
+  (sleep until-routine-done:literal routine2:integer)
 ])
diff --git a/mu.arc b/mu.arc
index dcbf5338..ac998383 100644
--- a/mu.arc
+++ b/mu.arc
@@ -250,6 +250,9 @@
       (> curr-cycle* rep.routine!sleep.1)
     until-location-changes
       (~is rep.routine!sleep.2 (memory* rep.routine!sleep.1))
+    until-routine-done
+      (find [and _ (is rep._!id rep.routine!sleep.1)]
+            completed-routines*)
     ))
 
 (on-init
@@ -587,6 +590,8 @@
                           (= rep.routine*!sleep `(until ,wakeup-time)))
                       until-location-changes
                         (= rep.routine*!sleep `(until-location-changes ,(addr arg.1) ,(m arg.1)))
+                      until-routine-done
+                        (= rep.routine*!sleep `(until-routine-done ,(m arg.1)))
                       ; else
                         (die "badly formed 'sleep' call @(tostring:prn (body.routine* pc.routine*))")
                       )
diff --git a/mu.arc.t b/mu.arc.t
index d12b109b..f9c2ef83 100644
--- a/mu.arc.t
+++ b/mu.arc.t
@@ -2882,6 +2882,32 @@
 (when (ran-to-completion 'f1)
   (prn "F - fork can specify a maximum cycle limit"))
 
+(reset)
+(new-trace "fork-then-wait")
+(add-code
+  '((function f1 [
+      { begin
+        (loop)
+      }
+     ])
+    (function main [
+      (1:integer/routine-id <- fork f1:fn nil:literal/globals 30:literal/limit)
+      (sleep until-routine-done:literal 1:integer/routine-id)
+      (2:integer <- copy 34:literal)
+     ])))
+(= scheduling-interval* 5)
+;? (= dump-trace* (obj whitelist '("schedule")))
+(run 'main)
+(each routine completed-routines*
+  (awhen rep.routine!error (prn "error - " it)))
+(check-trace-contents "scheduler orders functions correctly"
+  '(("schedule" "pushing main to sleep queue")
+    ("schedule" "scheduling f1")
+    ("schedule" "ran out of time")
+    ("schedule" "waking up main")
+  ))
+;? (quit)
+
 ; The scheduler needs to keep track of the call stack for each routine.
 ; Eventually we'll want to save this information in mu's address space itself,
 ; along with the types array, the magic buffers for args and oargs, and so on.