Scaffolding for handling the "when" of the run-request
[8sync.git] / loopy.scm
index f11b6b8503b2d235c00544b31956052ff718c28e..389d8e7a20dfe1583a8a911e47e39524eb4223eb 100644 (file)
--- a/loopy.scm
+++ b/loopy.scm
             make-time-segment time-segment?
             time-segment-time time-segment-queue
 
-            time-< time-= time-<=
+            time-< time-= time-<= time-+
+
+            <time-delta>
+            make-time-delta time-delta?
+            time-delta-sec time-delta-usec
 
             <schedule>
             make-schedule schedule?
 ;;;    and with reasonable separation from functional components?
 
 (define-immutable-record-type <agenda>
-  (make-agenda-intern queue prompt-tag port-mapping schedule)
+  (make-agenda-intern queue prompt-tag port-mapping schedule time)
   agenda?
   (queue agenda-queue)
   (prompt-tag agenda-prompt-tag)
   (port-mapping agenda-port-mapping)
-  (schedule agenda-schedule))
+  (schedule agenda-schedule)
+  (time agenda-time))
 
 (define (make-async-prompt-tag)
   (make-prompt-tag "prompt"))
@@ -74,8 +79,9 @@
                       (queue (make-q))
                       (prompt (make-prompt-tag))
                       (port-mapping (make-port-mapping))
-                      (schedule (make-schedule)))
-  (make-agenda-intern queue prompt port-mapping schedule))
+                      (schedule (make-schedule))
+                      (time (gettimeofday)))
+  (make-agenda-intern queue prompt port-mapping schedule time))
 
 
 \f
   (or (time-< time1 time2)
       (time-= time1 time2)))
 
+
+(define-record-type <time-delta>
+  (make-time-delta-intern sec usec)
+  time-delta?
+  (sec time-delta-sec)
+  (usec time-delta-usec))
+
+(define* (make-time-delta sec #:optional usec)
+  (make-time-delta-intern sec (or usec 0)))
+
+(define (time-+ time time-delta)
+  (cons (+ (car time) (time-delta-sec time-delta))
+        (+ (cdr time) (time-delta-usec time-delta))))
+
+
 (define-record-type <schedule>
   (make-schedule-intern segments)
   schedule?
              (agenda-run-once agenda))))
       (if (and stop-condition (stop-condition agenda))
           'done
-          (loop new-agenda)))))
+          (let ((updated-agenda
+                 ;; Adjust the agenda's time just in time
+                 ;; We do this here rather than in agenda-run-once to make
+                 ;; agenda-run-once's behavior fairly predictable
+                 (set-field new-agenda (agenda-time) (gettimeofday))))
+            (loop updated-agenda))))))
 
 (define (agenda-run-once agenda)
   "Run once through the agenda, and produce a new agenda
@@ -310,11 +336,16 @@ based on the results"
              (proc-result (call-proc proc))
              (enqueue
               (lambda (run-request)
-                (cond
-                 ((run-request-when run-request)
-                  (error "TODO"))
-                 (else
-                  (enq! next-queue (run-request-proc run-request)))))))
+                (match (run-request-when run-request)
+                  ((? time-delta? _)
+                   (error "TODO"))
+                  ((? integer? sec)
+                   (let ((time (cons sec 0)))
+                     (error "Also TODO")))
+                  (((? integer? sec) . (? integer? usec))
+                   (error "Also also TODO"))
+                  (#f
+                   (enq! next-queue (run-request-proc run-request)))))))
         ;; @@: We might support delay-wrapped procedures here
         (match proc-result
           ;; TODO: replace procedure with something that indicates