source: project/wiki/eggref/5/mailbox @ 38388

Last change on this file since 38388 was 38388, checked in by Kon Lovett, 14 months ago

extend example

File size: 9.2 KB
Line 
1[[tags: egg]]
2
3
4== mailbox
5
6[[toc:]]
7
8
9== Documentation
10
11Thread-safe queues with timeout.
12
13=== mailbox-timeout-condition?
14
15<procedure>(mailbox-timeout-condition? OBJ) --> boolean</procedure>
16
17Is the {{OBJ}} a mailbox timeout condition?
18
19A mailbox timeout condition is a composite condition of {{'exn}},
20{{'mailbox}}, and {{'timeout}} conditions.
21
22The {{'exn}} condition has properties of {{'location}}, {{'message}},
23{{'arguments}}, and {{'call-chain}}.
24
25The {{'mailbox}} condition has properties of {{'box}}.
26
27The {{'timeout}} condition has properties of {{'time}}, and {{'value}}.
28
29=== make-mailbox
30
31<procedure>(make-mailbox [NAME]) -> mailbox</procedure>
32
33Returns a new mailbox object.
34
35; {{NAME}} : {{*}} : default {{(gensym 'mailbox)}}
36
37* identify this mailbox.
38
39=== mailbox?
40
41<procedure>(mailbox? OBJ) --> boolean</procedure>
42
43Is the {{OBJ}} a {{mailbox}}?
44
45=== mailbox-name
46
47<procedure>(mailbox-name MAILBOX) -> *</procedure>
48
49Returns the name of {{MAILBOX}}.
50
51=== mailbox-empty?
52
53<procedure>(mailbox-empty? MAILBOX) -> boolean</procedure>
54
55If there are no queued objects in {{MAILBOX}}, returns {{#t}}, otherwise
56{{#f}}.
57
58=== mailbox-count
59
60<procedure>(mailbox-count MAILBOX) -> integer</procedure>
61
62Returns the number of queued objects for {{MAILBOX}}.
63
64=== mailbox-waiting?
65
66<procedure>(mailbox-waiting? MAILBOX) -> boolean</procedure>
67
68Is a thread waiting for {{MAILBOX}}?
69
70=== mailbox-waiters
71
72<procedure>(mailbox-waiters MAILBOX) -> (list-of thread)</procedure>
73
74Returns the threads waiting for {{MAILBOX}}.
75
76=== mailbox-send!
77
78<procedure>(mailbox-send! MAILBOX OBJ)</procedure>
79
80Queues the data object {{OBJ}}. If any threads exist that are waiting
81for input on {{MAILBOX}}, the execution of the first one will be
82resumed. The data will be read out of a mailbox in the same order in
83which is written in (in FIFO manner).
84
85=== mailbox-receive!
86
87<procedure>(mailbox-receive! MAILBOX [TIMEOUT [DEFAULT]]) -> *</procedure>
88
89If there is any data in {{MAILBOX}}, then the first object will be
90removed and returned as the result. If the mailbox is currently empty,
91the current thread will suspended until data is available.
92
93{{TIMEOUT}} is a [[http://srfi.schemers.org/srfi-18/srfi-18.html|SRFI-18]]
94{{time}} object or the real number of seconds.
95
96Should {{TIMEOUT}} be specified and occur the {{DEFAULT}}, if supplied, will be
97returned. Otherwise a mailbox timeout exception will be signaled for the
98calling thread. The {{DEFAULT}} value cannot be {{(void)}}.
99
100=== mailbox-wait!
101
102<procedure>(mailbox-wait! MAILBOX [TIMEOUT])</procedure>
103
104Similar to {{mailbox-receive!}}, but does not remove the received
105result from the queue of pending data.
106
107{{TIMEOUT}} is a [[http://srfi.schemers.org/srfi-18/srfi-18.html|SRFI-18]]
108{{time}} object or the real number of seconds.
109
110Should {{TIMEOUT}} be specified and occur a mailbox timeout exception
111will be signaled for the calling thread.
112
113=== mailbox-push-back!
114
115<procedure>(mailbox-push-back! MAILBOX OBJ)</procedure>
116
117Pushes the data object {{OBJ}} into the first position of a mailbox.
118
119=== mailbox-push-back-list!
120
121<procedure>(mailbox-push-back-list! MAILBOX OBJS)</procedure>
122
123Pushes the list of objects {{OBJS}} back into the mailbox, so that {{(car
124OBJS)}} becomes the next receivable item.
125
126=== make-mailbox-cursor
127
128<procedure>(make-mailbox-cursor MAILBOX) -> mailbox-cursor</procedure>
129
130Returns an object which can enumerate a mailbox.
131
132Multiple cursors can scan, and mutate, the same mailbox.
133
134=== mailbox-cursor?
135
136<procedure>(mailbox-cursor? OBJ) --> boolean</procedure>
137
138Is the {{OBJ}} a {{mailbox-cursor}}?
139
140=== mailbox-cursor-mailbox
141
142<procedure>(mailbox-cursor-mailbox MAILBOX-CURSOR) -> mailbox</procedure>
143
144Returns the mailbox object associated with the mailbox cursor.
145
146=== mailbox-cursor-next
147
148<procedure>(mailbox-cursor-next MAILBOX-CURSOR [TIMEOUT [DEFAULT]]) -> *</procedure>
149
150Returns the next object in the mailbox queue, waiting if necessary.
151
152The mailbox queue is scanned from oldest to newest.
153
154{{TIMEOUT}} is a [[http://srfi.schemers.org/srfi-18/srfi-18.html|SRFI-18]]
155{{time}} object or the real number of seconds.
156
157Should {{TIMEOUT}} be specified and occur the {{DEFAULT}}, if supplied, will be
158returned. Otherwise a mailbox timeout exception will be signaled for the
159calling thread. The {{DEFAULT}} value cannot be {{(void)}}.
160
161=== mailbox-cursor-rewind
162
163<procedure>(mailbox-cursor-rewind MAILBOX-CURSOR)</procedure>
164
165Position the cursor at the oldest message in the mailbox.
166
167=== mailbox-cursor-extract-and-rewind
168
169<procedure>(mailbox-cursor-extract-and-rewind MAILBOX-CURSOR)</procedure>
170
171Remove from the associated mailbox queue the last object returned by
172{{mailbox-cursor-next}} and position the cursor at the oldest message in the
173mailbox.
174
175The extraction is not performed without a previous call to
176{{mailbox-cursor-next}}.
177
178=== mailbox-cursor-rewound?
179
180<procedure>(mailbox-cursor-rewound? MAILBOX-CURSOR) -> boolean</procedure>
181
182Is {{MAILBOX-CURSOR}} positioned at the start of the mailbox queue?
183
184=== mailbox-cursor-unwound?
185
186<procedure>(mailbox-cursor-unwound? MAILBOX-CURSOR) -> boolean</procedure>
187
188Is {{MAILBOX-CURSOR}} positioned at the end of the mailbox queue?
189
190
191== Usage
192
193<enscript language=scheme>
194(import mailbox)
195</enscript>
196
197
198== Examples
199
200<enscript language=scheme>
201(import (chicken base))
202(import (srfi 18))
203(import mailbox)
204
205(define (say dir msg)
206  (print (thread-name (current-thread)) ": " dir ": " msg) )
207
208(define (producer ch x)
209  (make-thread
210    (lambda ()
211      (say "writing" x)
212      (mailbox-send! ch x) )
213    'producer) )
214
215(define (consumer ch)
216  (make-thread
217    (lambda ()
218      (let loop ()
219        (let ((x (mailbox-receive! ch)))
220          (say "read" x)
221          (unless (eq? 'quit x)
222            (loop) ) ) ) )
223    'consumer) )
224
225(define (running-producer! ch x) (thread-start! (producer ch x)))
226
227(define (independent-producer! ch x) (thread-join! (running-producer! ch x)))
228
229(define (running-consumer! ch) (thread-start! (consumer ch)))
230
231(define PRODUCT-LINE '(good better best))
232
233;order/fulfillment pipeline
234(let ((ch (make-mailbox)))
235  ;must have a customer before product
236  (let ((th-consumer (running-consumer! ch)))
237    ;now we can make something
238    (for-each
239      (cut independent-producer! ch <>)
240      (append PRODUCT-LINE '(quit)))
241    ;until satiated or the well runs dry
242    (thread-join! th-consumer) ) )
243</enscript>
244
245
246== Notes
247
248* '{{mailbox-wait!}}, {{mailbox-receive!}}, and {{mailbox-cursor-next}}, are
249susceptible to ''deadlock''. When a mailbox is empty the {{(current-thread)}}
250is suspended (indefinite block). Then the scheduler looks for the next ready
251thread. If one is not available it signals ''deadlock''. Using a {{TIMEOUT}}
252will allow the calling thread to unblock eventually.
253
254* A {{mailbox-cursor}} must live in an environment where {{mailbox}} entries
255are added and removed asynchronously. The cursor does '''not''' see a snapshot
256of the mailbox. The current state of the mailbox is queried.
257
258
259== Bugs & Limitations
260
261* {{mailbox-wait!}}, {{mailbox-receive!}}, and {{mailbox-cursor-next}} must
262not be used with a timeout value when the {{(current-thread)}} is the
263{{##sys#primordial-thread}}!
264
265== Author
266
267[[/users/felix winkelmann|felix winkelmann]]
268[[/users/kon lovett|Kon Lovett]]
269
270
271== Version history
272
273; 3.3.2 :
274; 3.3.1 : Removed {{miscmacros}} requirement.
275; 3.3.0 : Remove [[record-varinats]] requirement.
276; 3.2.0 : Remove [[condition-utils]] & [[check-errors]] requirements.
277; 3.0.0 : CHICKEN 5 release.
278; 2.3.1 : Fix name type.
279; 2.3.0 : Add types.
280; 2.2.3 :
281; 2.2.2 : Expand {{mailbox-timeout-condition}}.
282; 2.2.1 :
283; 2.2.0 : Included ''inline-type-checks.scm'' so all includes are egg-local.
284; 2.1.3 : Fix for resuming a thread when mailbox empty; reported by Jeronimo Pellegrini. Added {{mailbox-cursor-unwound?}}. The {{mailbox-name}} can be an arbitrary Scheme object.
285; 2.1.2 :
286; 2.1.1 :
287; 2.1.0 : Needs "check-errors" extension.
288; 2.0.0 : Port to hygienic Chicken.
289
290
291== License
292
293Copyright (c) 2003, Felix L. Winkelmann
294All rights reserved.
295
296Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
297conditions are met:
298
299  Redistributions of source code must retain the above copyright notice, this list of conditions and the following
300    disclaimer.
301  Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
302    disclaimer in the documentation and/or other materials provided with the distribution.
303  Neither the name of the author nor the names of its contributors may be used to endorse or promote
304    products derived from this software without specific prior written permission.
305
306THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
307OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
308AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
309CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
310CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
311SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
312THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
313OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
314POSSIBILITY OF SUCH DAMAGE.
Note: See TracBrowser for help on using the repository browser.