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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
(* thread.sml
* 2004 Matthew Fluet (mfluet@acm.org)
* Ported to MLton threads.
*)
(* thread.sml
*
* COPYRIGHT (c) 1995 AT&T Bell Laboratories.
* COPYRIGHT (c) 1989-1991 John H. Reppy
*)
structure Thread : THREAD =
struct
structure Assert = LocalAssert(val assert = false)
structure Debug = LocalDebug(val debug = false)
structure S = Scheduler
fun debug msg = Debug.sayDebug ([S.atomicMsg, S.tidMsg], msg)
fun debug' msg = debug (fn () => msg)
open ThreadID
fun generalExit (tid', clr') =
let
val () = Assert.assertNonAtomic' "Thread.generalExit"
val () = debug' "generalExit" (* NonAtomic *)
val () = Assert.assertNonAtomic' "Thread.generalExit"
in
S.switchToNext
(fn t =>
let
val tid as TID {dead, props, ...} = S.getThreadId t
val () = Assert.assert ([], fn () =>
concat ["Thread.generalExit ",
Option.getOpt (Option.map tidToString tid', "NONE"),
" <> ",
tidToString tid], fn () =>
case tid' of NONE => true
| SOME tid' => sameTid (tid', tid))
val () = if clr' then props := [] else ()
val () = Event.atomicCVarSet dead
in
()
end)
end
fun doHandler (TID {exnHandler, ...}, exn) =
(debug (fn () => concat ["Exception: ", exnName exn, " : ", exnMessage exn])
; ((!exnHandler) exn) handle _ => ())
fun spawnc f x =
let
val () = S.atomicBegin ()
fun thread tid () =
((f x) handle ex => doHandler (tid, ex)
; generalExit (SOME tid, false))
val t = S.new thread
val tid = S.getThreadId t
val () = S.ready (S.prep t)
val () = S.atomicEnd ()
val () = debug (fn () => concat ["spawnc ", tidToString tid]) (* NonAtomic *)
in
tid
end
fun spawn f = spawnc f ()
fun joinEvt (TID{dead, ...}) = Event.cvarGetEvt dead
val getTid = S.getCurThreadId
fun exit () =
let
val () = Assert.assertNonAtomic' "Thread.exit"
val () = debug' "exit" (* NonAtomic *)
val () = Assert.assertNonAtomic' "Thread.exit"
in
generalExit (NONE, true)
end
fun yield () =
let
val () = Assert.assertNonAtomic' "Thread.yield"
val () = debug' "yield" (* NonAtomic *)
val () = Assert.assertNonAtomic' "Thread.yield"
in
S.readyAndSwitchToNext (fn () => ())
end
(* thread-local data *)
local
fun mkProp () =
let
exception E of 'a
fun cons (a, l) = E a :: l
fun peek [] = NONE
| peek (E a :: _) = SOME a
| peek (_ :: l) = peek l
fun delete [] = []
| delete (E _ :: r) = r
| delete (x :: r) = x :: delete r
in
{cons = cons,
peek = peek,
delete = delete}
end
fun mkFlag () =
let
exception E
fun peek [] = false
| peek (E :: _) = true
| peek (_ :: l) = peek l
fun set (l, flg) =
let
fun set ([], _) = if flg then E::l else l
| set (E::r, xs) = if flg then l else List.revAppend(xs, r)
| set (x::r, xs) = set (r, x::xs)
in
set (l, [])
end
in
{set = set,
peek = peek}
end
fun getProps () =
let val TID {props, ...} = getTid ()
in props
end
in
fun newThreadProp (init : unit -> 'b) =
let
val {peek, cons, delete} = mkProp()
fun peekFn () = peek(!(getProps()))
fun getF () =
let val h = getProps()
in
case peek(!h) of
NONE => let val b = init()
in h := cons(b, !h); b
end
| (SOME b) => b
end
fun clrF () =
let val h = getProps()
in h := delete(!h)
end
fun setFn x =
let val h = getProps()
in h := cons(x, delete(!h))
end
in
{peekFn = peekFn,
getFn = getF,
clrFn = clrF,
setFn = setFn}
end
fun newThreadFlag () =
let
val {peek, set} = mkFlag()
fun getF ()= peek(!(getProps()))
fun setF flg =
let val h = getProps()
in h := set(!h, flg)
end
in
{getFn = getF,
setFn = setF}
end
end
end
|