src/Pure/System/system_channel.scala
changeset 45027 f459e93a038e
child 45028 d608dd8cd409
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Pure/System/system_channel.scala	Wed Sep 21 20:35:50 2011 +0200
@@ -0,0 +1,100 @@
+/*  Title:      Pure/System/system_channel.scala
+    Author:     Makarius
+
+Portable system channel for inter-process communication.
+*/
+
+package isabelle
+
+
+import java.io.{InputStream, OutputStream, File, FileInputStream, FileOutputStream, IOException}
+
+
+object System_Channel
+{
+  def apply(): System_Channel = new Fifo_Channel
+}
+
+abstract class System_Channel
+{
+  def isabelle_args: List[String]
+  def rendezvous(): (OutputStream, InputStream)
+  def accepted(): Unit
+}
+
+
+object Fifo_Channel
+{
+  private val next_fifo = new Counter
+}
+
+class Fifo_Channel extends System_Channel
+{
+  /* operations on named pipes */
+
+  private def mk_fifo(): String =
+  {
+    val i = Fifo_Channel.next_fifo()
+    val script =
+      "FIFO=\"/tmp/isabelle-fifo-${PPID}-$$" + i + "\"\n" +
+      "echo -n \"$FIFO\"\n" +
+      "mkfifo -m 600 \"$FIFO\"\n"
+    val (out, err, rc) = Isabelle_System.bash(script)
+    if (rc == 0) out else error(err.trim)
+  }
+
+  private def rm_fifo(fifo: String): Boolean =
+    Isabelle_System.platform_file(
+      Path.explode(if (Platform.is_windows) fifo + ".lnk" else fifo)).delete
+
+  private def fifo_input_stream(fifo: String): InputStream =
+  {
+    if (Platform.is_windows) { // Cygwin fifo as Windows/Java input stream
+      val proc =
+        Isabelle_System.execute(false,
+          Isabelle_System.standard_path(Path.explode("~~/lib/scripts/raw_dump")), fifo, "-")
+      proc.getOutputStream.close
+      proc.getErrorStream.close
+      proc.getInputStream
+    }
+    else new FileInputStream(fifo)
+  }
+
+  private def fifo_output_stream(fifo: String): OutputStream =
+  {
+    if (Platform.is_windows) { // Cygwin fifo as Windows/Java output stream
+      val proc =
+        Isabelle_System.execute(false,
+          Isabelle_System.standard_path(Path.explode("~~/lib/scripts/raw_dump")), "-", fifo)
+      proc.getInputStream.close
+      proc.getErrorStream.close
+      val out = proc.getOutputStream
+      new OutputStream {
+        override def close() { out.close(); proc.waitFor() }
+        override def flush() { out.flush() }
+        override def write(b: Array[Byte]) { out.write(b) }
+        override def write(b: Array[Byte], off: Int, len: Int) { out.write(b, off, len) }
+        override def write(b: Int) { out.write(b) }
+      }
+    }
+    else new FileOutputStream(fifo)
+  }
+
+
+  /* initialization */
+
+  private val fifo1 = mk_fifo()
+  private val fifo2 = mk_fifo()
+
+  val isabelle_args: List[String] = List ("-W", fifo1 + ":" + fifo2)
+
+  def rendezvous(): (OutputStream, InputStream) =
+  {
+    /*rendezvous*/
+    val output_stream = fifo_output_stream(fifo1)
+    val input_stream = fifo_input_stream(fifo2)
+    (output_stream, input_stream)
+  }
+
+  def accepted() { rm_fifo(fifo1); rm_fifo(fifo2) }
+}