35 handle exn => |
35 handle exn => |
36 if Exn.is_interrupt exn then reraise exn |
36 if Exn.is_interrupt exn then reraise exn |
37 else error_message (Runtime.exn_message exn); |
37 else error_message (Runtime.exn_message exn); |
38 |
38 |
39 |
39 |
40 (* thread names and input *) |
40 (* thread input *) |
41 |
41 |
42 datatype state = |
42 val thread_input = |
43 State of { |
43 Synchronized.var "Debugger.state" (Symtab.empty: string list Queue.T Symtab.table); |
44 threads: Thread.thread Symtab.table, (*thread name ~> thread*) |
|
45 input: string list Queue.T Symtab.table (*thread name ~> input queue*) |
|
46 }; |
|
47 |
|
48 fun make_state (threads, input) = State {threads = threads, input = input}; |
|
49 val init_state = make_state (Symtab.empty, Symtab.empty); |
|
50 fun map_state f (State {threads, input}) = make_state (f (threads, input)); |
|
51 |
|
52 val global_state = Synchronized.var "Debugger.state" init_state; |
|
53 |
|
54 fun cancel thread_name = |
|
55 Synchronized.change global_state (tap (fn State {threads, ...} => |
|
56 (case Symtab.lookup threads thread_name of |
|
57 NONE => () |
|
58 | SOME thread => Simple_Thread.interrupt_unsynchronized thread))); |
|
59 |
44 |
60 fun input thread_name msg = |
45 fun input thread_name msg = |
61 Synchronized.change global_state (map_state (fn (threads, input) => |
46 Synchronized.change thread_input |
62 let val input' = Symtab.map_default (thread_name, Queue.empty) (Queue.enqueue msg) input; |
47 (Symtab.map_default (thread_name, Queue.empty) (Queue.enqueue msg)); |
63 in (threads, input') end)); |
|
64 |
|
65 fun register_thread thread_name = |
|
66 Synchronized.change global_state (map_state (fn (threads, input) => |
|
67 let |
|
68 val threads' = Symtab.update_new (thread_name, Thread.self ()) threads |
|
69 handle Symtab.DUP _ => threads; |
|
70 in (threads', input) end)); |
|
71 |
48 |
72 fun get_input thread_name = |
49 fun get_input thread_name = |
73 Synchronized.guarded_access global_state (fn State {threads, input} => |
50 Synchronized.guarded_access thread_input (fn input => |
74 (case Symtab.lookup input thread_name of |
51 (case Symtab.lookup input thread_name of |
75 NONE => NONE |
52 NONE => NONE |
76 | SOME queue => |
53 | SOME queue => |
77 let |
54 let |
78 val (msg, queue') = Queue.dequeue queue; |
55 val (msg, queue') = Queue.dequeue queue; |
79 val input' = |
56 val input' = |
80 if Queue.is_empty queue' then Symtab.delete_safe thread_name input |
57 if Queue.is_empty queue' then Symtab.delete_safe thread_name input |
81 else Symtab.update (thread_name, queue') input; |
58 else Symtab.update (thread_name, queue') input; |
82 in SOME (msg, make_state (threads, input')) end)); |
59 in SOME (msg, input') end)); |
83 |
60 |
84 |
61 |
85 |
62 |
86 (** thread state **) |
63 (** thread state **) |
87 |
64 |
224 (SOME (fn (_, break) => |
201 (SOME (fn (_, break) => |
225 if not (is_debugging ()) andalso (! break orelse is_stepping ()) andalso |
202 if not (is_debugging ()) andalso (! break orelse is_stepping ()) andalso |
226 Options.default_bool @{system_option ML_debugger_active} |
203 Options.default_bool @{system_option ML_debugger_active} |
227 then |
204 then |
228 (case Simple_Thread.get_name () of |
205 (case Simple_Thread.get_name () of |
229 SOME thread_name => (register_thread thread_name; debugger_loop thread_name) |
206 SOME thread_name => debugger_loop thread_name |
230 | NONE => ()) |
207 | NONE => ()) |
231 else ())); |
208 else ())); |
232 |
209 |
233 end; |
210 end; |
234 |
211 |