syndicate-rkt/syndicate/engine.rkt

66 lines
2.7 KiB
Racket
Raw Normal View History

2021-05-27 09:28:10 +00:00
#lang racket/base
2021-06-04 14:20:14 +00:00
;;; SPDX-License-Identifier: LGPL-3.0-or-later
;;; SPDX-FileCopyrightText: Copyright © 2021 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
2021-05-27 09:28:10 +00:00
(provide engine?
engine-thread
engine-inhabitant-count
make-engine
adjust-inhabitant-count!
queue-task!
*dead-engine*)
2021-05-27 09:28:10 +00:00
2021-05-28 08:33:02 +00:00
(require racket/match)
2021-05-27 09:28:10 +00:00
(require (only-in racket/exn exn->string))
(require "support/counter.rkt")
2021-06-08 13:57:25 +00:00
(define-logger syndicate/engine)
2021-05-27 09:28:10 +00:00
(struct engine (id thread [inhabitant-count #:mutable])
#:methods gen:custom-write
[(define (write-proc e port mode)
(fprintf port "#<engine:~a>" (engine-id e)))])
(define generate-engine-id (make-counter))
(define (make-engine initial-inhabitant-count)
(define e (engine (generate-engine-id)
(thread (lambda ()
(thread-receive) ;; delay boot until we're ready
2021-06-08 13:57:25 +00:00
(log-syndicate/engine-debug "~a starting" e)
2021-05-27 09:28:10 +00:00
(with-handlers ([exn? (handle-unexpected-task-runner-termination e)])
(let loop ()
2021-06-08 13:57:25 +00:00
(log-syndicate/engine-debug
2021-05-27 09:28:10 +00:00
"~a task count: ~a" e (engine-inhabitant-count e))
2021-05-28 08:33:02 +00:00
(if (positive? (engine-inhabitant-count e))
;; We have some non-daemon users so just block
(begin ((thread-receive))
(loop))
;; No non-daemon users, so keep running until there's no more work
(match (thread-try-receive)
[#f ;; No work, no non-daemons, we're done.
(void)]
[thunk
(thunk)
(loop)])))
2021-06-08 13:57:25 +00:00
(log-syndicate/engine-debug "~a stopping" e))))
2021-05-27 09:28:10 +00:00
initial-inhabitant-count))
(thread-send (engine-thread e) 'boot)
e)
(define (adjust-inhabitant-count! e delta)
(queue-task! e (lambda ()
(set-engine-inhabitant-count! e (+ (engine-inhabitant-count e) delta)))))
(define ((handle-unexpected-task-runner-termination e) exn)
2021-06-08 13:57:25 +00:00
(log-syndicate/engine-error "~a terminated unexpectedly!\n~a" e (exn->string exn))
2021-05-27 09:28:10 +00:00
(exit 1))
(define (queue-task! e thunk)
(thread-send (engine-thread e)
thunk
(lambda ()
(log-syndicate/engine-warning "Attempt to enqueue task for dead engine ~v" e))))
(define *dead-engine* (make-engine 0))