author | wenzelm |
Mon, 05 Aug 2013 15:03:52 +0200 | |
changeset 52861 | e93d73b51fd0 |
parent 52800 | 1baa5d19ac44 |
child 56333 | 38f1422ef473 |
permissions | -rw-r--r-- |
52584 | 1 |
(* Title: Pure/System/message_channel.ML |
2 |
Author: Makarius |
|
3 |
||
4 |
Preferably asynchronous channel for Isabelle messages. |
|
5 |
*) |
|
6 |
||
7 |
signature MESSAGE_CHANNEL = |
|
8 |
sig |
|
52800
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
9 |
type message |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
10 |
val message: string -> Properties.T -> string -> message |
52584 | 11 |
type T |
52800
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
12 |
val send: T -> message -> unit |
52584 | 13 |
val shutdown: T -> unit |
14 |
val make: System_Channel.T -> T |
|
15 |
end; |
|
16 |
||
17 |
structure Message_Channel: MESSAGE_CHANNEL = |
|
18 |
struct |
|
19 |
||
52800
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
20 |
(* message *) |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
21 |
|
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
22 |
datatype message = Message of string list; |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
23 |
|
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
24 |
fun chunk s = [string_of_int (size s), "\n", s]; |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
25 |
|
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
26 |
fun message name raw_props body = |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
27 |
let |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
28 |
val robust_props = map (pairself YXML.embed_controls) raw_props; |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
29 |
val header = YXML.string_of (XML.Elem ((name, robust_props), [])); |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
30 |
in Message (chunk header @ chunk body) end; |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
31 |
|
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
32 |
fun output_message channel (Message ss) = |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
33 |
List.app (System_Channel.output channel) ss; |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
34 |
|
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
35 |
|
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
36 |
(* flush *) |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
37 |
|
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
38 |
fun flush channel = ignore (try System_Channel.flush channel); |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
39 |
|
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
40 |
val flush_message = message Markup.protocolN Markup.flush ""; |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
41 |
fun flush_output channel = (output_message channel flush_message; flush channel); |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
42 |
|
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
43 |
|
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
44 |
(* channel *) |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
45 |
|
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
46 |
datatype T = Message_Channel of {send: message -> unit, shutdown: unit -> unit}; |
52584 | 47 |
|
48 |
fun send (Message_Channel {send, ...}) = send; |
|
49 |
fun shutdown (Message_Channel {shutdown, ...}) = shutdown (); |
|
50 |
||
51 |
fun message_output mbox channel = |
|
52 |
let |
|
53 |
fun loop receive = |
|
54 |
(case receive mbox of |
|
52800
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
55 |
SOME NONE => flush_output channel |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
56 |
| SOME (SOME msg) => |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
57 |
(output_message channel msg; |
52584 | 58 |
loop (Mailbox.receive_timeout (seconds 0.02))) |
52800
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
59 |
| NONE => (flush_output channel; loop (SOME o Mailbox.receive))); |
52584 | 60 |
in fn () => loop (SOME o Mailbox.receive) end; |
61 |
||
62 |
fun make channel = |
|
63 |
if Multithreading.available then |
|
64 |
let |
|
65 |
val mbox = Mailbox.create (); |
|
66 |
val thread = Simple_Thread.fork false (message_output mbox channel); |
|
52800
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
67 |
fun send msg = Mailbox.send mbox (SOME msg); |
52584 | 68 |
fun shutdown () = |
69 |
(Mailbox.send mbox NONE; Mailbox.await_empty mbox; Simple_Thread.join thread); |
|
70 |
in Message_Channel {send = send, shutdown = shutdown} end |
|
71 |
else |
|
72 |
let |
|
52800
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
73 |
fun send msg = (output_message channel msg; flush channel); |
1baa5d19ac44
less aggressive flushing: cope with massive amounts of protocol messages, e.g. from threads_trace;
wenzelm
parents:
52584
diff
changeset
|
74 |
in Message_Channel {send = send, shutdown = fn () => ()} end; |
52584 | 75 |
|
76 |
end; |
|
77 |