File: condition-variable.jl

package info (click to toggle)
librep 0.90.2-1.3
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 3,940 kB
  • sloc: ansic: 32,948; lisp: 11,025; sh: 9,844; makefile: 545; sed: 93
file content (122 lines) | stat: -rw-r--r-- 3,400 bytes parent folder | download | duplicates (3)
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
113
114
115
116
117
118
119
120
121
122
#| condition-variable.jl -- condition variables

   $Id$

   Copyright (C) 2000 John Harper <jsh@users.sourceforge.net>

   This file is part of librep.

   librep is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   librep is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with librep; see the file COPYING.  If not, write to
   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|#

(define-structure rep.threads.condition-variable

    (export make-condition-variable
	    condition-variable-p
	    condition-variable-wait
	    condition-variable-signal
	    condition-variable-broadcast)

    (open rep
	  rep.data.datums
	  rep.threads
	  rep.threads.utils
	  rep.threads.mutex)

  (define key (cons))

  (define (make-condition-variable) (make-datum '() key))
  (define (condition-variable-p arg) (has-type-p arg key))

  (define-datum-printer key (lambda (arg stream)
			      (declare (unused arg))
			      (write stream "#<condition-variable>")))

  (define (cv-ref cv) (datum-ref cv key))
  (define (cv-set cv x) (datum-set cv key x))

  (define (condition-variable-wait cv mutex #!optional timeout)
    (let ((thread (current-thread))
	  (acquired nil))
      (unless (memq thread (cv-ref cv))
	(cv-set cv (cons thread (cv-ref cv))))
      (without-interrupts
       ;; these two operations are atomic to prevent people
       ;; signalling the condition before we actually suspend
       (release-mutex mutex)
       (setq acquired (not (thread-suspend thread timeout))))
      (obtain-mutex mutex)
      acquired))

  (define (condition-variable-signal cv)
    (when (cv-ref cv)
      (let ((thread (last (cv-ref cv))))
	(cv-set cv (delq thread (cv-ref cv)))
	(thread-wake thread))))

  (define (condition-variable-broadcast cv)
    (let ((threads (cv-ref cv)))
      (cv-set cv '())
      ;; wake in fifo order
      (mapc thread-wake (nreverse threads)))))


#| Test program:

(structure ()

  (open	rep
	rep.system
	rep.threads
	rep.threads.mutex
	rep.threads.condition-variable)

  (define mutex (make-mutex))
  (define access (make-condition-variable))
  (define count 0)
  (define data 0)

  (define (producer n)
    (do ((i 1 (+ i 1)))
	((> i n))
      (obtain-mutex mutex)
      (while (= count 1)
	(condition-variable-wait access mutex))
      (setq data i)
      (setq count (1+ count))
      (condition-variable-signal access)
      (release-mutex mutex)))

  (define (consumer n)
    (do ((i 1 (+ i 1)))
	((> i n))
      (obtain-mutex mutex)
      (while (= count 0)
	(condition-variable-wait access mutex))
      (format standard-error "consumed: %d\n" data)
      (setq count (1- count))
      (condition-variable-signal access)
      (release-mutex mutex)))

  (let* ((arg (get-command-line-option "--num" t))
	 (n (if arg (string->number arg) 5))
	 (c (make-thread (lambda () (consumer n)))))

    ;; run the producer thread..
    (producer n)

    ;; ..then wait for the consumer to terminate
    (thread-join c)))
|#