I\'m looking to replace a lot of my perl with scala. One of the things I tend to do a lot is call binaries (usually compiled C++, but could be java, other perl scripts, q sc
Have you considered spawning a new thread which will then call the blocking method process.exitValue()? You can then call your callback.
updated version using spawn
to create a new thread that blocks and waits for the exit code
class Exe(command:String, out:String=>Unit, err:String=>Unit, onExit:Int=>Unit) {
import scala.sys.process._
import scala.io._
import java.io._
import scala.concurrent._
import scala.concurrent.ops.spawn
val inputStream = new SyncVar[OutputStream];
val process = Process(command).run(
new ProcessIO(
stdin => inputStream.put(stdin),
stdout => Source.fromInputStream(stdout).getLines.foreach(out),
stderr => Source.fromInputStream(stderr).getLines.foreach(err)));
spawn { onExit(process.exitValue()) }
def write(s:String):Unit = synchronized {
inputStream.get.write((s + "\n").getBytes)
}
def close():Unit = {
inputStream.get.close
}
}
can use like this
import java.util.concurrent.CountDownLatch
val latch = new CountDownLatch(1)
val exe = new Exe("tr [a-z] [A-Z]",
out => println("o: " + out),
err => println("e: " + err),
code=> {println(code) ; latch.countDown() })
exe.write("lower")
exe.close()
latch.await
prints
o: LOWER
0
thanks everyone!
You can wait for the end of a process calling exitValue
. You might do that in a separate thread, in which the callback will happen. Maybe class Process
could be pimped thus:
import scala.concurrent.ops.spawn
implicit def ProcessWithCallback(p: Process) {
def whenTerminatedDo(callback: Int => Unit) = spawn{
val exitValue = p.exitValue; callback(p)
}
}
You could then use that in Exe
as you like.
The Process
class given by the JVM and wrapped by scala.sys.Process
is really rather feable, it will be hard not to block a thread