src/Pure/System/message_channel.ML
author wenzelm
Wed, 10 Jul 2013 23:25:28 +0200
changeset 52584 5cad4a5f5615
child 52800 1baa5d19ac44
permissions -rw-r--r--
more abstract message channel;
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
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
     9
  type T
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    10
  val send: T -> string list -> bool -> unit
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    11
  val shutdown: T -> unit
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    12
  val make: System_Channel.T -> T
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    13
end;
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    14
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    15
structure Message_Channel: MESSAGE_CHANNEL =
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    16
struct
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    17
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    18
datatype T = Message_Channel of
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    19
 {send: string list -> bool -> unit,
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    20
  shutdown: unit -> unit};
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    21
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    22
fun send (Message_Channel {send, ...}) = send;
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    23
fun shutdown (Message_Channel {shutdown, ...}) = shutdown ();
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    24
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    25
fun flush channel = ignore (try System_Channel.flush channel);
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    26
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    27
fun message_output mbox channel =
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    28
  let
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    29
    fun loop receive =
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    30
      (case receive mbox of
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    31
        SOME NONE => flush channel
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    32
      | SOME (SOME (msg, do_flush)) =>
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    33
         (List.app (fn s => System_Channel.output channel s) msg;
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    34
          if do_flush then flush channel else ();
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    35
          loop (Mailbox.receive_timeout (seconds 0.02)))
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    36
      | NONE => (flush channel; loop (SOME o Mailbox.receive)));
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    37
  in fn () => loop (SOME o Mailbox.receive) end;
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    38
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    39
fun make channel =
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    40
  if Multithreading.available then
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    41
    let
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    42
      val mbox = Mailbox.create ();
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    43
      val thread = Simple_Thread.fork false (message_output mbox channel);
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    44
      fun send msg do_flush = Mailbox.send mbox (SOME (msg, do_flush));
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    45
      fun shutdown () =
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    46
        (Mailbox.send mbox NONE; Mailbox.await_empty mbox; Simple_Thread.join thread);
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    47
    in Message_Channel {send = send, shutdown = shutdown} end
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    48
  else
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    49
    let
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    50
      fun send msg = (List.app (fn s => System_Channel.output channel s) msg; flush channel);
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    51
    in Message_Channel {send = fn msg => fn _ => send msg, shutdown = fn () => ()} end;
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    52
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    53
end;
5cad4a5f5615 more abstract message channel;
wenzelm
parents:
diff changeset
    54