src/Pure/System/message_channel.ML
author wenzelm
Mon, 05 Aug 2013 15:03:52 +0200
changeset 52861 e93d73b51fd0
parent 52800 1baa5d19ac44
child 56333 38f1422ef473
permissions -rw-r--r--
commands with overlay remain visible, to avoid loosing printed output;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
52584
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
     1
(*  Title:      Pure/System/message_channel.ML
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
     3
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
     4
Preferably asynchronous channel for Isabelle messages.
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
     5
*)
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
     6
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
     7
signature MESSAGE_CHANNEL =
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
     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
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    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
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    13
  val shutdown: T -> unit
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    14
  val make: System_Channel.T -> T
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    15
end;
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    16
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    17
structure Message_Channel: MESSAGE_CHANNEL =
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    18
struct
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    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
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    47
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    48
fun send (Message_Channel {send, ...}) = send;
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    49
fun shutdown (Message_Channel {shutdown, ...}) = shutdown ();
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    50
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    51
fun message_output mbox channel =
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    52
  let
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    53
    fun loop receive =
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    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
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    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
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    60
  in fn () => loop (SOME o Mailbox.receive) end;
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    61
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    62
fun make channel =
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    63
  if Multithreading.available then
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    64
    let
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    65
      val mbox = Mailbox.create ();
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    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
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    68
      fun shutdown () =
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    69
        (Mailbox.send mbox NONE; Mailbox.await_empty mbox; Simple_Thread.join thread);
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    70
    in Message_Channel {send = send, shutdown = shutdown} end
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    71
  else
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    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
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    75
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    76
end;
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    77