19 |
|
|
20 |
type 'a cond (* condition with value *) |
type 'a cond (* condition with value *) |
21 |
|
|
22 |
val fork : (unit -> 'a) -> 'a cond (* termination condition with value *) |
val fork : (unit -> 'a) -> 'a cond (* termination condition with value |
23 |
val wait : 'a cond -> 'a |
* (thread initially waits with |
24 |
val wait' : int -> 'a cond -> 'a |
* extremely low urgency) *) |
25 |
|
val wait : 'a cond -> 'a (* wait with low urgency *) |
26 |
|
val waitU : int -> 'a cond -> 'a (* wait with given urgency, |
27 |
|
* (urgency is always higher than |
28 |
|
* when waiting using "wait") *) |
29 |
|
|
30 |
val inputReady : TextIO.instream -> unit cond |
val inputReady : TextIO.instream -> unit cond |
31 |
val ucond : unit -> unit cond |
val ucond : unit -> unit cond |
32 |
val signal : unit cond -> unit |
val signal : unit cond -> unit |
117 |
|
|
118 |
fun wait c = wait' 0 c |
fun wait c = wait' 0 c |
119 |
|
|
120 |
|
fun waitU u c = wait' (u + 1) c |
121 |
|
|
122 |
fun fork worker = let |
fun fork worker = let |
123 |
val c = ref (Waiting []) |
val c = ref (Waiting []) |
124 |
in |
in |
125 |
|
(* We give new workers a low priority so that any threads that |
126 |
|
* were already running but are now waiting for some event |
127 |
|
* get control first if they are re-enabled. This is because |
128 |
|
* waiting threads will clean up after errors in which case |
129 |
|
* we don't want new threads to run off. *) |
130 |
SMLofNJ.Cont.callcc (fn return => |
SMLofNJ.Cont.callcc (fn return => |
131 |
(SMLofNJ.Cont.callcc (fn ts => (enqueue ((ts, 0), runable); |
(SMLofNJ.Cont.callcc (fn ts => (enqueue ((ts, ~1), runable); |
132 |
SMLofNJ.Cont.throw return c)); |
SMLofNJ.Cont.throw return c)); |
133 |
wakeup (c, worker ()); |
wakeup (c, worker ()); |
134 |
schedule ())) |
schedule ())) |