1 open Posix
.Signal MLton
.Signal
3 (* Translated from prodcons
.ocaml
. *)
4 fun for (start
, stop
, f
) =
9 else (f i
; loop (i
+ 1))
21 val enque
: 'a t
* 'a
-> unit
22 val deque
: 'a t
-> 'a option
25 datatype 'a t
= T
of {front
: 'a list ref
, back
: 'a list ref
}
27 fun new () = T
{front
= ref
[], back
= ref
[]}
29 fun enque (T
{back
, ...}, x
) = back
:= x
:: !back
31 fun deque (T
{front
, back
}) =
35 | l
=> let val l
= rev l
37 [] => raise Fail
"deque"
38 | x
:: l
=> (back
:= []; front
:= l
; SOME x
)
40 | x
:: l
=> (front
:= l
; SOME x
)
47 val spawn
: (unit
-> unit
) -> unit
48 val yield
: unit
-> unit
54 val lock
: t
* string -> unit
63 val wait
: t
* Mutex
.t
-> unit
68 open Itimer Signal Thread
70 val topLevel
: Thread
.Runnable
.t option ref
= ref NONE
73 val threads
: Thread
.Runnable
.t Queue
.t
= Queue
.new ()
75 fun ready t
: unit
= Queue
.enque (threads
, t
)
76 fun next () : Thread
.Runnable
.t
=
77 case Queue
.deque threads
of
78 NONE
=> (print
"switching to toplevel\n"
83 fun 'a
exit (): 'a
= switch (fn _
=> next ())
85 fun new (f
: unit
-> unit
): Thread
.Runnable
.t
=
87 (Thread
.new (fn () => ((f () handle _
=> exit ())
96 fun yield (): unit
= switch (fn t
=> schedule (Thread
.prepare (t
, ())))
98 val spawn
= ready
o new
101 Itimer
.set (Itimer
.Real,
107 (topLevel
:= SOME (Thread
.prepare (t
, ()))
108 ; new (fn () => (setHandler (alrm
, Handler
.handler schedule
)
109 ; setItimer (Time
.fromMilliseconds
20)))))
110 ; setItimer Time
.zeroTime
116 datatype t
= T
of {locked
: bool ref
,
117 waiting
: unit Thread
.t Queue
.t
}
120 T
{locked
= ref
false,
121 waiting
= Queue
.new ()}
123 fun lock (T
{locked
, waiting
, ...}, name
) =
126 (print (concat
[name
, " lock looping\n"])
127 ; Thread
.atomicBegin ()
129 then (print
"mutex is locked\n"
132 ; Queue
.enque (waiting
, t
)
135 else (print
"mutex is not locked\n"
137 ; Thread
.atomicEnd ()))
141 fun safeUnlock (T
{locked
, waiting
, ...}) =
143 ; (case Queue
.deque waiting
of
145 | SOME t
=> (print
"unlock found waiting thread\n"
146 ; ready (Thread
.prepare (t
, ())))))
149 (print
"unlock atomicBegin\n"
150 ; Thread
.atomicBegin ()
152 ; Thread
.atomicEnd ())
155 structure Condition
=
157 datatype t
= T
of {waiting
: unit Thread
.t Queue
.t
}
159 fun new () = T
{waiting
= Queue
.new ()}
161 fun wait (T
{waiting
, ...}, m
) =
164 ; print
"wait unlocked mutex\n"
165 ; Queue
.enque (waiting
, t
)
167 ; Mutex
.lock (m
, "wait"))
169 fun signal (T
{waiting
, ...}) =
170 case Queue
.deque waiting
of
172 | SOME t
=> ready (Thread
.prepare (t
, ()))
177 structure Mutex
= Thread
.Mutex
178 structure Condition
= Thread
.Condition
185 val c
= Condition
.new ()
189 (print (concat
["producer acquiring lock ", Int.toString i
, "\n"])
190 ; Mutex
.lock (m
, "producer")
191 ; print
"producer acquired lock\n"
192 ; while !count
= 1 do Condition
.wait (c
, m
)
193 ; print
"producer passed condition\n"
197 ; print
"producer releasing lock\n"
199 ; print
"producer released lock\n"
200 ; produced
:= !produced
+ 1))
206 (print (concat
["consumer acquiring lock ", Int.toString (!i
), "\n"])
207 ; Mutex
.lock (m
, "consumer")
208 ; print
"consumer acquired lock\n"
209 ; while !count
= 0 do Condition
.wait (c
, m
)
213 ; print
"consumer releasing lock\n"
215 ; print
"consumer released lock\n"
216 ; consumed
:= !consumed
+ 1)
219 fun atoi s
= case Int.fromString s
of SOME num
=> num | NONE
=> 0
220 fun printl
[] = TextIO.print
"\n" |
printl (h
::t
) = ( TextIO.print h
; printl t
)
222 fun main (name
, args
) =
224 val n
= atoi (hd (args @
["1"]))
225 val p
= Thread
.spawn (fn () => producer n
)
226 val c
= Thread
.spawn (fn () => consumer n
)
227 val _
= Thread
.run ()
228 val _
= Posix
.Process
.sleep (Time
.fromSeconds
1)
229 val _
= printl
[Int.toString (!produced
),
231 Int.toString (!consumed
)]
236 val _
= main ( "prodcons", ["100000"] )