source: branches/1.1.x/src/org/armedbear/lisp/threads.lisp

Last change on this file was 14106, checked in by ehuelsmann, 12 years ago

Move exports from the THREADS package to threads.lisp.
Move sockets related exports to socket.lisp, fixing symbol references

to refer to the EXTENSIONS package instead of SYSTEM.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 4.5 KB
Line 
1;;; threads.lisp
2;;;
3;;; Copyright (C) 2009-2010 Erik Huelsmann <ehuelsmann@common-lisp.net>
4;;;
5;;; $Id: threads.lisp 14106 2012-08-17 10:45:00Z ehuelsmann $
6;;;
7;;; This program is free software; you can redistribute it and/or
8;;; modify it under the terms of the GNU General Public License
9;;; as published by the Free Software Foundation; either version 2
10;;; of the License, or (at your option) any later version.
11;;;
12;;; This program is distributed in the hope that it will be useful,
13;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15;;; GNU General Public License for more details.
16;;;
17;;; You should have received a copy of the GNU General Public License
18;;; along with this program; if not, write to the Free Software
19;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20;;;
21;;; As a special exception, the copyright holders of this library give you
22;;; permission to link this library with independent modules to produce an
23;;; executable, regardless of the license terms of these independent
24;;; modules, and to copy and distribute the resulting executable under
25;;; terms of your choice, provided that you also meet, for each linked
26;;; independent module, the terms and conditions of the license of that
27;;; module.  An independent module is a module which is not derived from
28;;; or based on this library.  If you modify this library, you may extend
29;;; this exception to your version of the library, but you are not
30;;; obligated to do so.  If you do not wish to do so, delete this
31;;; exception statement from your version.
32
33(in-package #:threads)
34
35
36(export '(make-mailbox mailbox-send mailbox-empty-p
37          mailbox-read mailbox-peek
38          make-thread-lock with-thread-lock
39          make-mutex get-mutex release-mutex with-mutex))
40
41
42;;
43;; MAKE-THREAD helper to establish restarts
44;;
45
46(defun thread-function-wrapper (fun)
47  (restart-case
48      (funcall fun)
49    (abort () :report "Abort thread.")))
50
51;;
52;; Mailbox implementation
53;;
54
55;; this export statement is also in autoloads.lisp
56(export '(make-mailbox mailbox-send mailbox-empty-p mailbox-read mailbox-peek))
57
58(defstruct mailbox
59  queue)
60
61(defun mailbox-send (mailbox item)
62  "Sends an item into the mailbox, notifying 1 waiter
63to wake up for retrieval of that object."
64  (threads:synchronized-on mailbox
65     (push item (mailbox-queue mailbox))
66     (threads:object-notify mailbox)))
67
68(defun mailbox-empty-p (mailbox)
69  "Returns non-NIL if the mailbox can be read from, NIL otherwise."
70  ;; Because we're just checking the value of an object reference,
71  ;; (which are atomically gotten and set) we don't need to lock
72  ;; the mailbox before operating on it.
73  (null (mailbox-queue mailbox)))
74
75(defun mailbox-read (mailbox)
76  "Blocks on the mailbox until an item is available for reading.
77When an item is available, it is returned."
78  (threads:synchronized-on mailbox
79     (loop
80        (unless (mailbox-empty-p mailbox)
81          (return))
82        (object-wait mailbox))
83     (pop (mailbox-queue mailbox))))
84
85(defun mailbox-peek (mailbox)
86  "Returns two values. The second returns non-NIL when the mailbox
87is empty. The first is the next item to be read from the mailbox.
88
89Note that due to multi-threading, the first value returned upon
90peek, may be different from the one returned upon next read in the
91calling thread."
92  (threads:synchronized-on mailbox
93     (values (car (mailbox-queue mailbox))
94             (null (mailbox-queue mailbox)))))
95
96
97
98;;
99;; Mutex implementation
100;;
101
102
103;; this export statement is also in autoloads.lisp
104(export '(make-mutex get-mutex release-mutex))
105
106(defstruct mutex
107  in-use)
108
109(defun get-mutex (mutex)
110  "Acquires a lock on the `mutex'."
111  (synchronized-on mutex
112    (loop
113       while (mutex-in-use mutex)
114       do (object-wait mutex))
115    (setf (mutex-in-use mutex) T)))
116
117(defun release-mutex (mutex)
118  "Releases a lock on the `mutex'."
119  (synchronized-on mutex
120    (setf (mutex-in-use mutex) NIL)
121    (object-notify mutex)))
122
123(defmacro with-mutex ((mutex) &body body)
124  "Acquires a lock on `mutex', executes the body
125and releases the lock."
126  (let ((m (gensym)))
127    `(let ((,m ,mutex))
128       (when (get-mutex ,m)
129         (unwind-protect
130          (progn
131            ,@body)
132          (release-mutex ,m))))))
133
134
135;;
136;; Lock implementation
137;;
138
139(defun make-thread-lock ()
140  "Returns an object to be used with the `with-thread-lock' macro."
141  (gensym))
142
143(defmacro with-thread-lock ((lock) &body body)
144  "Acquires a lock on the `lock', executes `body' and releases the lock."
145  (let ((glock (gensym)))
146    `(let ((,glock ,lock))
147       (synchronized-on ,glock
148          ,@body))))
149
Note: See TracBrowser for help on using the repository browser.