;;; 8sync --- Asynchronous programming for Guile
-;;; Copyright (C) 2015 Christopher Allan Webber <cwebber@dustycloud.org>
+;;; Copyright © 2015, 2016, 2017 Christopher Allan Webber <cwebber@dustycloud.org>
;;;
;;; This file is part of 8sync.
;;;
;;; License along with 8sync. If not, see <http://www.gnu.org/licenses/>.
(define-module (8sync repl)
- #:use-module (ice-9 q)
- #:use-module (8sync agenda)
+ #:use-module (oop goops)
+ #:use-module (8sync)
+ #:use-module (8sync daydream)
+ #:use-module (srfi srfi-1)
+ #:use-module (system repl server)
#:use-module (system repl coop-server)
- #:export (make-coop-server-handler
- spawn-and-queue-repl-server!))
+ #:export (<repl-manager>))
-(define (make-coop-server-handler coop-server)
- (define (run-self)
- (poll-coop-repl-server coop-server)
- ;; queue ourselves again
- (run-delay (run-self) (/ 1 30)))
- run-self)
+(define-actor <repl-manager> (<actor>)
+ ((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)
+ (socket #:init-value #f
+ #:accessor .socket)
+ (poll-every #:init-keyword #:poll-every
+ #:init-value (/ 1 30)
+ #:getter .poll-every)
+ (subscribers #:init-keyword #:subscribers
+ #:init-value '()
+ #:accessor .subscribers))
-(define* (spawn-and-queue-repl-server! agenda #:optional port)
- (let ((coop-server
- (if port
- (spawn-coop-repl-server port)
- (spawn-coop-repl-server))))
- (enq! (agenda-queue agenda)
- (make-coop-server-handler coop-server))))
+(define-method (actor-cleanup! (repl-manager <repl-manager>))
+ ;; Close the socket, if open
+ (and=> (.socket repl-manager)
+ close)
+ ;; Delete the file, if it exists
+ (when (file-exists? (.path repl-manager))
+ (delete-file (.path repl-manager))))
+
+(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
+ (spawn-coop-repl-server socket))
+ (define (inform-subscribers)
+ (for-each
+ (lambda (subscriber)
+ (<- subscriber 'repl-update))
+ (.subscribers repl-manager)))
+ (set! (.socket repl-manager) socket)
+ (while #t
+ (daydream (.poll-every repl-manager))
+ (poll-coop-repl-server server)
+ (inform-subscribers)))
+
+(define (repl-manager-add-subscriber repl-manager message)
+ (define from (message-from message))
+ (unless (member from (.subscribers repl-manager))
+ (set! (.subscribers repl-manager)
+ (cons from (.subscribers repl-manager)))))
+
+(define (repl-manager-remove-subscriber repl-manager message)
+ (define from (message-from message))
+ (set! (.subscribers repl-manager)
+ (remove (lambda (x) (equal? x (message-from message)))
+ (.subscribers repl-manager))))