X-Git-Url: https://jxself.org/git/?p=8sync.git;a=blobdiff_plain;f=8sync%2Fagenda.scm;h=eba0139fa2268f526430ae73f00285ab0e215e4b;hp=3c4270fa1ab99a1fe66c0d9e1801e2584755cc19;hb=0a4fe47d9b6fe7c13296562b5408f68d0083da71;hpb=cabcb051a6201a907749c4fa46993af1e38013f9 diff --git a/8sync/agenda.scm b/8sync/agenda.scm index 3c4270f..eba0139 100644 --- a/8sync/agenda.scm +++ b/8sync/agenda.scm @@ -64,9 +64,14 @@ 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 + %8sync-run %8sync-run-at %8sync-run-delay %8sync-port catch-8sync catch-%8sync @@ -78,6 +83,8 @@ print-error-and-continue + stop-on-nothing-to-do + %current-agenda start-agenda agenda-run-once)) @@ -453,6 +460,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,12 +560,37 @@ 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 port-request-args ...) + (make-run-request kont))))) + +(define-syntax-rule (%port-remove-request port) (make-async-request (lambda (kont) - (list (make-port-request port-request-args ...) + (list (make-port-remove-request port) (make-run-request kont))))) + +;; 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 ...))) + + ;; TODO: Write (%run-immediately) ;; TODO @@ -586,7 +625,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) @@ -663,7 +704,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)) @@ -671,6 +714,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)))) @@ -679,8 +723,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 @@ -710,6 +773,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 @@ -783,11 +847,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