(in-package #:candle) (defvar *mutex* (sb-thread:make-mutex)) (defvar *waitq* (sb-thread:make-waitqueue)) (defvar *job-system*) (defgeneric process-job-in-system (job-system job)) (defgeneric shutdown-system (job-system)) (defun start-processor-thread () (format t "Starting processor in ~(~A~) mode~%" *job-system*) (let* ((active t) (processor-thread (sb-thread:make-thread (lambda () (loop :while active :do (let ((job (find :queued *all-job* :key #'job-status))) (if job (process-job job) ; We just wait here until the processor is released, which is usually done ; when a project is refreshed. (sb-thread:with-mutex (*mutex*) (sb-thread:condition-wait *waitq* *mutex*)))))) :name "Processor"))) (push (lambda () (format t "Shutting down processor thread~%") (setf active nil) (awaken-processor-thread) (sb-thread:join-thread processor-thread) (shutdown-system *job-system*)) sb-ext:*exit-hooks*))) (defun awaken-processor-thread () (sb-thread:with-mutex (*mutex*) (sb-thread:condition-broadcast *waitq*))) (defun process-job (job) (set-job-status job :in-progress) (git (job-project job) "checkout" (job-sha job)) (if (not (probe-file (format nil "~A.candle" (project-dir (job-project job))))) (set-job-status job :no-candle-file) (multiple-value-bind (result log) (process-job-in-system *job-system* job) (set-job-status job (if result :succeeded :failed)) (set-job-log job log))))