49 lines
1.8 KiB
Racket
49 lines
1.8 KiB
Racket
#lang racket/base
|
|
|
|
(provide engine?
|
|
engine-thread
|
|
engine-inhabitant-count
|
|
make-engine
|
|
adjust-inhabitant-count!
|
|
queue-task!)
|
|
|
|
(require (only-in racket/exn exn->string))
|
|
(require "support/counter.rkt")
|
|
|
|
(define-logger syndicate/task)
|
|
|
|
(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
|
|
(log-syndicate/task-info "~a starting" e)
|
|
(with-handlers ([exn? (handle-unexpected-task-runner-termination e)])
|
|
(let loop ()
|
|
(log-syndicate/task-debug
|
|
"~a task count: ~a" e (engine-inhabitant-count e))
|
|
(when (positive? (engine-inhabitant-count e))
|
|
((thread-receive))
|
|
(loop)))
|
|
(log-syndicate/task-info "~a stopping" e))))
|
|
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)
|
|
(log-syndicate/task-error "~a terminated unexpectedly!\n~a" e (exn->string exn))
|
|
(exit 1))
|
|
|
|
(define (queue-task! e thunk)
|
|
(thread-send (engine-thread e) thunk))
|