Source file picos_mux_thread.ml
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
open Picos
type t = {
fiber : Fiber.t;
mutex : Mutex.t;
condition : Condition.t;
fatal_exn_handler : exn -> unit;
}
let create ~fatal_exn_handler fiber =
let mutex = Mutex.create () and condition = Condition.create () in
{ fiber; mutex; condition; fatal_exn_handler }
let rec block trigger t =
if not (Trigger.is_signaled trigger) then begin
Mutex.lock t.mutex;
match
if not (Trigger.is_signaled trigger) then
Condition.wait t.condition t.mutex
with
| () ->
Mutex.unlock t.mutex;
block trigger t
| exception async_exn ->
Mutex.unlock t.mutex;
raise async_exn
end
let resume trigger t _ =
let _is_canceled : bool = Fiber.unsuspend t.fiber trigger in
begin
match Mutex.lock t.mutex with
| () -> Mutex.unlock t.mutex
| exception Sys_error _ ->
()
end;
Condition.broadcast t.condition
let default_fatal_exn_handler exn =
prerr_string "Fatal error: exception ";
prerr_string (Printexc.to_string exn);
prerr_char '\n';
Printexc.print_backtrace stderr;
flush stderr;
exit 2
let[@alert "-handler"] rec await t trigger =
if Fiber.try_suspend t.fiber trigger t t resume then block trigger t;
Fiber.canceled t.fiber
and current t =
t.fiber
and yield t =
Fiber.check t.fiber;
Thread.yield ()
and cancel_after : type a. _ -> a Computation.t -> _ =
fun t computation ~seconds exn_bt ->
Fiber.check t.fiber;
Select.cancel_after computation ~seconds exn_bt
and spawn t fiber main =
Fiber.check t.fiber;
Thread.create start (fiber, t.fatal_exn_handler, main) |> ignore
and handler = Handler.{ current; spawn; yield; cancel_after; await }
and start (fiber, fatal_exn_handler, main) =
try Handler.using handler (create ~fatal_exn_handler fiber) main
with exn -> fatal_exn_handler exn
let run_fiber ?(fatal_exn_handler = default_fatal_exn_handler) fiber main =
Select.check_configured ();
Handler.using handler (create ~fatal_exn_handler fiber) main
let run ?(forbid = false) ?fatal_exn_handler main =
let computation = Computation.create ~mode:`LIFO () in
let fiber = Fiber.create ~forbid computation in
let main _ = Computation.capture computation main () in
run_fiber ?fatal_exn_handler fiber main;
Computation.peek_exn computation