repl: Add spawn-repl, a simpler cooperative repl interface using spawn-fiber.
[8sync.git] / 8sync / repl.scm
index 2825c0224650c3fbf855eecc556fd1cbf6bfaaa9..ddcd50b0f168d82748dc2ee0e74182c8407af9a1 100644 (file)
 (define-module (8sync repl)
   #:use-module (oop goops)
   #:use-module (8sync)
+  #:use-module (fibers)
+  #:use-module (8sync daydream)
   #:use-module (srfi srfi-1)
+  #:use-module (ice-9 atomic)
   #:use-module (system repl server)
   #:use-module (system repl coop-server)
-  #:export (<repl-manager>))
+  #:export (<repl-manager>
+            spawn-repl))
 
 (define-actor <repl-manager> (<actor>)
-  ((*cleanup* repl-manager-cleanup)
-   (*init* repl-manager-init)
-   (add-subscriber repl-manager-add-subscriber)
-   (remove-subscriber repl-manager-remove-subscriber))
+  ((add-subscriber repl-manager-add-subscriber)
+   (remove-subscriber repl-manager-remove-subscriber)
+   (main-loop repl-manager-main-loop))
   (path #:init-keyword #:path
         #:init-value "/tmp/8sync-socket"
         #:getter .path)
@@ -41,7 +44,7 @@
                #:init-value '()
                #:accessor .subscribers))
 
-(define (repl-manager-cleanup repl-manager message)
+(define-method (actor-cleanup! (repl-manager <repl-manager>))
   ;; Close the socket, if open
   (and=> (.socket repl-manager)
          close)
   (when (file-exists? (.path repl-manager))
     (delete-file (.path repl-manager))))
 
-(define (repl-manager-init repl-manager message)
+(define-method (actor-init! (repl-manager <repl-manager>))
+  (<- (actor-id repl-manager) 'main-loop))
+
+(define-method (repl-manager-main-loop repl-manager message)
   (define socket
     (make-unix-domain-server-socket #:path (.path repl-manager)))
   (define server
        (<- subscriber 'repl-update))
      (.subscribers repl-manager)))
   (set! (.socket repl-manager) socket)
-  (while (actor-alive? repl-manager)
+  (while #t
+    (daydream (.poll-every repl-manager))
     (poll-coop-repl-server server)
-    (inform-subscribers)
-    (8sleep (.poll-every repl-manager))))
+    (inform-subscribers)))
 
 (define (repl-manager-add-subscriber repl-manager message)
   (define from (message-from message))
   (set! (.subscribers repl-manager)
         (remove (lambda (x) (equal? x (message-from message)))
                 (.subscribers repl-manager))))
+
+\f
+
+(define* (spawn-repl #:key (path "/tmp/8sync-socket")
+                     (socket (make-unix-domain-server-socket #:path path))
+                     (poll-every 1/30)
+                     (stop? (make-atomic-box #f))
+                     (on-update #f))
+  "Spawn a cooperative REPL in a new fiber."
+  (define server
+    (spawn-coop-repl-server socket))
+  (spawn-fiber
+   (lambda ()
+     (while (not (atomic-box-ref stop?))
+       ;; Poll the server
+       (poll-coop-repl-server server)
+       ;; Call update hook, if any
+       (and on-update (on-update))
+       ;; Take a break!
+       (sleep poll-every))
+     (close socket))))