src/Pure/System/message_channel.ML
author wenzelm
Tue, 13 Apr 2021 11:44:47 +0200
changeset 73577 6c8fc3c038eb
parent 73564 a021bb558feb
child 73578 629868f96c81
permissions -rw-r--r--
tuned signature;

(*  Title:      Pure/System/message_channel.ML
    Author:     Makarius

Preferably asynchronous channel for Isabelle messages.
*)

signature MESSAGE_CHANNEL =
sig
  type T
  val send_message: T -> string -> Properties.T -> XML.body list -> unit
  val shutdown: T -> unit
  val make: BinIO.outstream -> T
end;

structure Message_Channel: MESSAGE_CHANNEL =
struct

datatype message = Message of XML.body list;
datatype T = Message_Channel of {send: message -> unit, shutdown: unit -> unit};

fun send_message (Message_Channel {send, ...}) name raw_props chunks =
  let
    val robust_props = map (apply2 YXML.embed_controls) raw_props;
    val header = [XML.Elem ((name, robust_props), [])];
  in send (Message (header :: chunks)) end;

fun shutdown (Message_Channel {shutdown, ...}) = shutdown ();

fun message_output mbox stream =
  let
    fun continue () = Mailbox.receive NONE mbox |> received
    and received [] = continue ()
      | received (NONE :: _) = ()
      | received (SOME (Message chunks) :: rest) =
          (Byte_Message.write_message_yxml stream chunks; received rest);
  in continue end;

fun make stream =
  let
    val mbox = Mailbox.create ();
    val thread =
      Isabelle_Thread.fork {name = "channel", stack_limit = NONE, interrupts = false}
        (message_output mbox stream);
    fun send msg = Mailbox.send mbox (SOME msg);
    fun shutdown () =
      (Mailbox.send mbox NONE; Mailbox.await_empty mbox; Isabelle_Thread.join thread);
  in Message_Channel {send = send, shutdown = shutdown} end;

end;