-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathsingle-reader-mailbox.lisp
More file actions
112 lines (97 loc) · 3.88 KB
/
single-reader-mailbox.lisp
File metadata and controls
112 lines (97 loc) · 3.88 KB
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
;; single-reader-mailbox.lisp
;; --------------------------------------------------------------------------------------
;; Single-reader-mailboxes = queues with a lock
;; These mailboxes are intended for use by a single reader thread.
;; Multiple readers would need additional locking. (DM/SD 02/09)
;;
;; Copyright (C) 2008 by SpectroDynamics, LLC. All rights reserved.
;;
;; DM/SD 08/08
;; --------------------------------------------------------------------------------------
;; --------------------------------------------------------------------------------------
(in-package :single-reader-mailbox)
;; --------------------------------------------------------------------------------------
(defstruct (mailbox
(:include queue:queue))
(lock (mpcompat:make-lock) :read-only t)
(condv (mpcompat:make-condition-variable) :read-only t))
;; ----------------------------------------------------------------
(defun create ()
(make-mailbox))
;; ----------------------------------------------------------------
(defun send (msg mbox)
(with-accessors ((lock mailbox-lock)
(condv mailbox-condv)) mbox
(mpcompat:with-spinlock (lock)
(queue:add msg mbox)
(mpcompat:condition-variable-signal condv)) ))
;; ----------------------------------------------------------------
(defun receive (mbox &optional timeout (timeout-error-p t) timeout-value)
(with-accessors ((lock mailbox-lock)
(condv mailbox-condv)) mbox
(mpcompat:with-spinlock (lock)
(if (or (not-empty mbox)
(mpcompat:condition-variable-wait condv lock
:wait-reason "Waiting for mail"
:timeout timeout))
(queue:pop mbox) ;; returns val, t/f
;; else
(if timeout-error-p
(error "Timed out waiting for mail")
;; else
(values timeout-value nil) )))))
;; ----------------------------------------------------------------
#|
(defun selective-receive (mbox fn
&optional
exit-at-end
timeout
(timeout-error-p t)
timeout-value)
(let ((lock (mailbox-lock mbox)))
(labels ((get-head ()
(mpcompat:with-spinlock (lock)
(cdr (queue:tail mbox))))
(iter (cursor follow)
(let ((msg (car cursor)))
(if (funcall fn msg)
(mpcompat:with-spinlock (lock)
(queue:remove-at mbox (or follow (queue:tail mbox)))
(values msg t))
;; else
(if (eq cursor (queue:tail mbox))
(if exit-at-end
(values nil nil)
;; else
(multiple-value-bind (ans found)
(wait-for-message cursor)
(if found
(iter (cdr cursor) cursor)
;; else
(values ans nil))))
;; else
(iter (cdr cursor) cursor))
)))
(wait-for-message (last)
(if (mpcompat:process-wait-with-timeout
"Waiting for mail" timeout
(lambda ()
(not (eq last (queue:tail mbox)))))
(values t t)
;; else
(if timeout-error-p
(error "Timed out waiting for mail")
;; else
(values timeout-value nil)))) )
(if (not-empty mbox)
(iter (get-head) nil)
;; else
(multiple-value-bind (ans found)
(wait-for-message nil)
(if found
(iter (get-head) nil)
;; else
(values ans nil))
))
)))
|#