src/Pure/System/system_channel.scala
author wenzelm
Sun, 22 Jul 2012 23:31:57 +0200
changeset 49440 0d95980e9aae
parent 49424 0d2114eb412a
child 50710 8f61d1c7dded
permissions -rw-r--r--
parallel scheduling of jobs;
misc tuning;
wenzelm@45919
     1
/*  Title:      Pure/System/system_channel.scala
wenzelm@45919
     2
    Author:     Makarius
wenzelm@45919
     3
wenzelm@45920
     4
Portable system channel for inter-process communication, based on
wenzelm@45920
     5
named pipes or sockets.
wenzelm@45919
     6
*/
wenzelm@45919
     7
wenzelm@45919
     8
package isabelle
wenzelm@45919
     9
wenzelm@45919
    10
wenzelm@49424
    11
import java.io.{InputStream, OutputStream, File => JFile, FileInputStream,
wenzelm@49424
    12
  FileOutputStream, IOException}
wenzelm@45920
    13
import java.net.{ServerSocket, InetAddress}
wenzelm@45919
    14
wenzelm@45919
    15
wenzelm@45919
    16
object System_Channel
wenzelm@45919
    17
{
wenzelm@45931
    18
  def apply(use_socket: Boolean = false): System_Channel =
wenzelm@46031
    19
    if (Platform.is_windows) new Socket_Channel else new Fifo_Channel
wenzelm@45919
    20
}
wenzelm@45919
    21
wenzelm@45919
    22
abstract class System_Channel
wenzelm@45919
    23
{
wenzelm@45919
    24
  def isabelle_args: List[String]
wenzelm@45919
    25
  def rendezvous(): (OutputStream, InputStream)
wenzelm@45919
    26
  def accepted(): Unit
wenzelm@45919
    27
}
wenzelm@45919
    28
wenzelm@45919
    29
wenzelm@45920
    30
/** named pipes **/
wenzelm@45920
    31
wenzelm@46122
    32
private object Fifo_Channel
wenzelm@45919
    33
{
wenzelm@46114
    34
  private val next_fifo = Counter()
wenzelm@45919
    35
}
wenzelm@45919
    36
wenzelm@46122
    37
private class Fifo_Channel extends System_Channel
wenzelm@45919
    38
{
wenzelm@45919
    39
  private def mk_fifo(): String =
wenzelm@45919
    40
  {
wenzelm@45919
    41
    val i = Fifo_Channel.next_fifo()
wenzelm@45919
    42
    val script =
wenzelm@45919
    43
      "FIFO=\"/tmp/isabelle-fifo-${PPID}-$$" + i + "\"\n" +
wenzelm@45919
    44
      "echo -n \"$FIFO\"\n" +
wenzelm@45919
    45
      "mkfifo -m 600 \"$FIFO\"\n"
wenzelm@45919
    46
    val (out, err, rc) = Isabelle_System.bash(script)
wenzelm@45919
    47
    if (rc == 0) out else error(err.trim)
wenzelm@45919
    48
  }
wenzelm@45919
    49
wenzelm@45919
    50
  private def rm_fifo(fifo: String): Boolean =
wenzelm@49388
    51
    Path.explode(if (Platform.is_windows) fifo + ".lnk" else fifo).file.delete
wenzelm@45919
    52
wenzelm@45919
    53
  private def fifo_input_stream(fifo: String): InputStream =
wenzelm@45919
    54
  {
wenzelm@46031
    55
    require(!Platform.is_windows)
wenzelm@46031
    56
    new FileInputStream(fifo)
wenzelm@45919
    57
  }
wenzelm@45919
    58
wenzelm@45919
    59
  private def fifo_output_stream(fifo: String): OutputStream =
wenzelm@45919
    60
  {
wenzelm@46031
    61
    require(!Platform.is_windows)
wenzelm@46031
    62
    new FileOutputStream(fifo)
wenzelm@45919
    63
  }
wenzelm@45919
    64
wenzelm@45919
    65
wenzelm@45919
    66
  private val fifo1 = mk_fifo()
wenzelm@45919
    67
  private val fifo2 = mk_fifo()
wenzelm@45919
    68
wenzelm@45919
    69
  val isabelle_args: List[String] = List ("-W", fifo1 + ":" + fifo2)
wenzelm@45919
    70
wenzelm@45919
    71
  def rendezvous(): (OutputStream, InputStream) =
wenzelm@45919
    72
  {
wenzelm@45919
    73
    val output_stream = fifo_output_stream(fifo1)
wenzelm@45919
    74
    val input_stream = fifo_input_stream(fifo2)
wenzelm@45919
    75
    (output_stream, input_stream)
wenzelm@45919
    76
  }
wenzelm@45919
    77
wenzelm@45919
    78
  def accepted() { rm_fifo(fifo1); rm_fifo(fifo2) }
wenzelm@45919
    79
}
wenzelm@45920
    80
wenzelm@45920
    81
wenzelm@45920
    82
/** sockets **/
wenzelm@45920
    83
wenzelm@46122
    84
private class Socket_Channel extends System_Channel
wenzelm@45920
    85
{
wenzelm@45920
    86
  private val server = new ServerSocket(0, 2, InetAddress.getByName("127.0.0.1"))
wenzelm@45920
    87
wenzelm@45920
    88
  def isabelle_args: List[String] = List("-T", "127.0.0.1:" + server.getLocalPort)
wenzelm@45920
    89
wenzelm@45920
    90
  def rendezvous(): (OutputStream, InputStream) =
wenzelm@45920
    91
  {
wenzelm@45920
    92
    val socket = server.accept
wenzelm@45920
    93
    (socket.getOutputStream, socket.getInputStream)
wenzelm@45920
    94
  }
wenzelm@45920
    95
wenzelm@45920
    96
  def accepted() { server.close }
wenzelm@45920
    97
}