X-Git-Url: https://jxself.org/git/?p=8sync.git;a=blobdiff_plain;f=8sync%2Fagenda.scm;h=da398458db34096d2893d61286456ee9ad156ab1;hp=c2614ef471cef514b14f3a7878a1523ea453c603;hb=d059d67fdc1e547f6d55b2883e5b0cc2f14f0380;hpb=9bb036f18457a6c2d24343e21e6950f9df5043e7 diff --git a/8sync/agenda.scm b/8sync/agenda.scm index c2614ef..da39845 100644 --- a/8sync/agenda.scm +++ b/8sync/agenda.scm @@ -64,9 +64,15 @@ port-request-port port-request-read port-request-write port-request-except + + make-port-remove-request port-remove-request port-remove-request? + port-remove-request-port + run-it wrap wrap-apply run run-at run-delay - %port-request %run %run-at %run-delay + %run %run-at %run-delay %port-request %port-remove-request + %8sync-run %8sync-run-at %8sync-run-delay + %8sync-port %8sync-port-remove catch-8sync catch-%8sync @@ -78,6 +84,8 @@ print-error-and-continue + stop-on-nothing-to-do + %current-agenda start-agenda agenda-run-once)) @@ -453,6 +461,13 @@ Will produce (0 . 0) instead of a negative number, if needed." (define port-request make-port-request) +(define-record-type + (make-port-remove-request port) + port-remove-request? + (port port-remove-request-port)) + +(define port-remove-request make-port-remove-request) + ;;; Asynchronous escape to run things @@ -546,11 +561,42 @@ return the wrong thing via (%8sync) and trip themselves up." (define-syntax-rule (%run-delay body ... delay-time) (%run-at body ... (tdelta delay-time))) -(define-syntax-rule (%port-request add-this-port port-request-args ...) +(define-syntax-rule (%port-request port port-request-args ...) (make-async-request (lambda (kont) - (list (make-port-request port-request-args ...) - (make-run-request kont))))) + (list (make-port-request port port-request-args ...) + (make-run-request kont #f))))) + +(define-syntax-rule (%port-remove-request port) + (make-async-request + (lambda (kont) + (list (make-port-remove-request port) + (make-run-request kont #f))))) + + +;; Sugar +(define-syntax-rule (%8sync-run rest ...) + "Sugar for (%8sync (%run ...))" + (%8sync (%run rest ...))) + +(define-syntax-rule (%8sync-run-at rest ...) + "Sugar for (%8sync (%run-at ...))" + (%8sync (%run-at rest ...))) + +(define-syntax-rule (%8sync-run-delay rest ...) + "Sugar for (%8sync (%run-delay ...))" + (%8sync (%run-delay rest ...))) + +(define-syntax-rule (%8sync-port rest ...) + "Sugar for (%8sync (%port-request ...))" + (%8sync (%port-request rest ...))) + +(define-syntax-rule (%8sync-port-remove rest ...) + "Sugar for (%8sync (%port-remove-request ...))" + (%8sync (%port-remove-request rest ...))) + + +;; TODO: Write (%run-immediately) ;; TODO (define-syntax-rule (%run-with-return return body ...) @@ -584,7 +630,9 @@ return the wrong thing via (%8sync) and trip themselves up." (define %current-agenda (make-parameter #f)) (define (update-agenda-from-select! agenda) - "Potentially (select) on ports specified in agenda, adding items to queue" + "Potentially (select) on ports specified in agenda, adding items to queue. + +Also handles sleeping when all we have to do is wait on the schedule." (define (hash-keys hash) (hash-map->list (lambda (k v) k) hash)) (define (get-wait-time) @@ -661,7 +709,9 @@ return the wrong thing via (%8sync) and trip themselves up." (has-items? agenda-write-port-map) (has-items? agenda-except-port-map))) - (if (ports-to-select?) + (if (or (ports-to-select?) + ;; select doubles as sleep... + (not (schedule-empty? (agenda-schedule agenda)))) (update-agenda) agenda)) @@ -669,6 +719,7 @@ return the wrong thing via (%8sync) and trip themselves up." "Update an agenda for a port-request" (define (handle-selector request-selector port-map-selector) (if (request-selector port-request) + ;; @@: Should we remove if #f? (hash-set! (port-map-selector agenda) (port-request-port port-request) (request-selector port-request)))) @@ -677,8 +728,27 @@ return the wrong thing via (%8sync) and trip themselves up." (handle-selector port-request-except agenda-except-port-map)) +(define (agenda-handle-port-remove-request! agenda port-remove-request) + "Update an agenda for a port-remove-request" + (let ((port (port-remove-request-port port-remove-request))) + (hash-remove! (agenda-read-port-map agenda) port) + (hash-remove! (agenda-write-port-map agenda) port) + (hash-remove! (agenda-except-port-map agenda) port))) + + +(define (stop-on-nothing-to-do agenda) + (and (q-empty? (agenda-queue agenda)) + (schedule-empty? (agenda-schedule agenda)) + (= 0 (hash-count (const #t) (agenda-read-port-map agenda))) + (= 0 (hash-count (const #t) (agenda-write-port-map agenda))) + (= 0 (hash-count (const #t) (agenda-except-port-map agenda))))) + + (define* (start-agenda agenda - #:key stop-condition + #:key + ;; @@: Should we make stop-on-nothing-to-do + ;; the default stop-condition? + stop-condition (get-time gettimeofday) (handle-ports update-agenda-from-select!)) ;; TODO: Document fields @@ -708,6 +778,7 @@ return the wrong thing via (%8sync) and trip themselves up." (agenda-queue agenda)) (loop agenda)))))) + (define (print-error-and-continue key . args) "Frequently used as pre-unwind-handler for agenda" (cond @@ -781,11 +852,14 @@ based on the results" (#f (enq! next-queue (run-request-proc run-request)))))))) (define (handle-individual result) + ;; @@: Could maybe optimize by switching to an explicit cond... (match result ((? run-request? new-proc) (enqueue new-proc)) ((? port-request? port-request) (agenda-handle-port-request! agenda port-request)) + ((? port-remove-request? port-remove-request) + (agenda-handle-port-remove-request! agenda port-remove-request)) ;; do nothing (_ #f))) ;; @@: We might support delay-wrapped procedures here