-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsleep-timers.lisp
55 lines (49 loc) · 2.21 KB
/
sleep-timers.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
(in-package #:harlie)
;; This mechanism written by Nikodemus Siivola <[email protected]>
(defclass task ()
((thread :initform nil :reader task-thread)
(lock :initform (bordeaux-threads:make-lock "Task Lock") :reader task-lock)
(control-lock :initform (bordeaux-threads:make-lock "Task Control Lock") :accessor task-control-lock)
(name :initarg :name :reader task-name)
(function :initarg :function :reader task-function)
(interval :initarg :interval :accessor task-interval)))
(defun stop-task (task)
(bordeaux-threads:with-recursive-lock-held ((task-control-lock task))
(bordeaux-threads:with-recursive-lock-held ((task-lock task))
(setf (slot-value task 'interval) nil))
(let ((thread (task-thread task)))
(when thread
(bordeaux-threads:join-thread thread)))
(setf (slot-value task 'thread) nil)))
(defun start-task (task interval &optional (function (task-function task)))
(tagbody
(log:info "Entering start-task~%")
(bordeaux-threads:with-recursive-lock-held ((task-control-lock task))
(log:info "Inside recursive lock in start-task~%")
(when (task-interval task)
(let ((thread (task-thread task)))
(when (and thread (bordeaux-threads:thread-alive-p thread))
(go :oops))))
(setf (slot-value task 'interval) interval
(slot-value task 'function) function
(slot-value task 'thread)
(bordeaux-threads:make-thread
(lambda ()
(log:info "Entering outer thunk.~%")
(loop for s = (bordeaux-threads:with-recursive-lock-held ((task-lock task))
(task-interval task))
while s
do (sleep s)
(funcall (task-function task)))
;;(format t "Outer thunk exiting.~%")
)
:name (task-name task))))
(return-from start-task task)
:oops
(error "Task already running.")))
(defmethod initialize-instance :after ((task task) &key)
(let ((interval (task-interval task)))
(when interval
(start-task task interval))))
(defun make-task (function interval name)
(make-instance 'task :function function :interval interval :name name))