Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | (* Copyright (C) 1999-2006 Henry Cejtin, Matthew Fluet, Suresh |
2 | * Jagannathan, and Stephen Weeks. | |
3 | * | |
4 | * MLton is released under a BSD-style license. | |
5 | * See the file MLton-LICENSE for details. | |
6 | *) | |
7 | ||
8 | structure Engine: ENGINE = | |
9 | struct | |
10 | ||
11 | datatype 'a t = T of {return: 'a res Thread.t option ref, | |
12 | thread: Thread.Runnable.t} | |
13 | and 'a res = | |
14 | Done of 'a | |
15 | | Raise of exn | |
16 | | TimeOut of 'a t | |
17 | ||
18 | val which = Itimer.Real | |
19 | val signal = Itimer.signal which | |
20 | ||
21 | fun done (return): unit = | |
22 | (return := NONE | |
23 | ; Itimer.set (which, {value = Time.zero, | |
24 | interval = Time.zero}) | |
25 | ; Signal.setHandler (signal, Signal.Handler.default)) | |
26 | ||
27 | fun new (f: unit -> 'a): 'a t = | |
28 | let | |
29 | val return = ref NONE | |
30 | val thread = | |
31 | Thread.new | |
32 | (fn () => | |
33 | let | |
34 | val res = Done (f ()) handle e => Raise e | |
35 | val ret = valOf (!return) | |
36 | val _ = done return | |
37 | in | |
38 | Thread.switch (fn _ => Thread.prepare (ret, res)) | |
39 | end) | |
40 | val thread = Thread.prepare (thread, ()) | |
41 | in | |
42 | T {return = return, thread = thread} | |
43 | end | |
44 | ||
45 | fun run (T {return, thread}, time: Time.t): 'a res = | |
46 | Thread.switch | |
47 | (fn cur: 'a res Thread.t => | |
48 | let | |
49 | val _ = return := SOME cur | |
50 | fun handler (me: Thread.Runnable.t): Thread.Runnable.t = | |
51 | Thread.prepare | |
52 | (Thread.prepend (cur, fn () => (done return | |
53 | ; TimeOut (T {return = return, | |
54 | thread = me}))), | |
55 | ()) | |
56 | val _ = Signal.setHandler (signal, Signal.Handler.handler handler) | |
57 | val _ = Itimer.set (which, {value = time, | |
58 | interval = Time.zero}) | |
59 | in | |
60 | thread | |
61 | end) | |
62 | ||
63 | fun timeLimit (t: Time.t, f: unit -> 'a): 'a option = | |
64 | case run (new f, t) of | |
65 | Done a => SOME a | |
66 | | Raise e => raise e | |
67 | | TimeOut _ => NONE | |
68 | ||
69 | fun repeat {thunk, limit, tries} = | |
70 | let | |
71 | fun loop (n: int) = | |
72 | if n <= 0 | |
73 | then NONE | |
74 | else (case timeLimit (limit, thunk) of | |
75 | NONE => loop (n - 1) | |
76 | | SOME a => SOME a) | |
77 | in loop tries | |
78 | end | |
79 | ||
80 | end |