Skip to content

Instantly share code, notes, and snippets.

@vtjnash
Forked from Keno/streams
Created December 8, 2012 04:21
Show Gist options
  • Save vtjnash/4238603 to your computer and use it in GitHub Desktop.
Save vtjnash/4238603 to your computer and use it in GitHub Desktop.
Howto and overview of new I/O system:
Using spawn and run
-------------------
Commands are specified with backticks as before:
julia> `echo test`
`echo test`
Cmd objects can be asynchronously executed using ``spawn`` or executed
as ususal using ``run``. However, by default spawn will not pass parent
STDIO to the child:
julia> run(`echo test`)
test
true
julia> spawn(`echo test`)
Process(`echo test`, ProcessRunning())
``spawn`` and ``run`` both optionally take a Stream to be read from/written to.
Be careful when using these with ``spawn`` though, as julia will proceed as
usual and may cause strange interactions. E.g.
julia> spawn(`echo test`,STDIN,STDOUT,STDERR)
Process(`echo test`, ProcessRunning())
julia> test
julia> run(`echo test`,STDIN,STDOUT,STDERR)
test
true
Note that the "test\n" that caused the second julia prompt is the one from
echo. The following also works:
julia> spawn(`echo test` > STDOUT)
Process(`echo test`, ProcessRunning())
julia> test
julia> Base.spawn_nostdin(`echo test`,STDOUT)
Process(`echo test`, ProcessRunning())
julia> test
``spawn_nostdin`` may or may not be exported in the future.
The old piping operations are supported as well.
Streams
-------
All streams are subtypes of ``AsyncStream``. In the examples above, STDOUT,
STDIN and STDERR were used though any stream should work:
julia> Base.connect_to_host("localhost",uint16(2000))
TcpSocket(Ptr{Void} @0x0000000105488cc0,true,true,IOString([],true,true,false,true,0,9223372036854775807,1),false,[],false,[],false,[])
julia> spawn(`echo test`>ans)
Process(`echo test`, ProcessRunning())
A server running on localhost:2000 (e.g.`nc -l 2000`), receive the string "test".
Operations on streams are asynchronous by design (see below for API), but
the usual synchronous methods exist as well:
julia> read_from(`git status`)
(NamedPipe(Ptr{Void} @0x0000000107346300,IOString([],true,true,false,true,0,9223372036854775807,1),true,true,false,[],false,[]),Process(`git status`, ProcessRunning()))
julia> pipe = ans[1]
julia> a=zeros(Uint8,2000); read(pipe,a); readall(pipe)
"o commit but untracked files present (use \"git add\" to track)\n"
Asynchronous interface
----------------------
libuv and Julia's I/O system built upon it is inherently asynchronous.
This asynchronous API is at the moment considered somewhat low-lvel,
though a high level asynchronous API (or just a cleanup and thorough
documentation of the current one) will certainly come at some point. The
following callbacks are available at the moment:
- connectcb(sock::AsyncStream, status::Int32) #On TcpSocks from connect
- connectioncb(sock::AsyncStream, status::Int32) # " " from listen
- readcb(stream, nreadable) #New data is available in the buffer
- closecb(handle) #Called when libuv has closed and is done with all
resources associated with the handle
- exitcb(proc, exit_status, term_signal) #A process has exited
There's also a few other ones relating to timers, etc. and a few internal
ones that are not listed here. These can be dealt with in a future revision
To see how all this work consider the following example:
julia> Base.open_any_tcp_port(uint16(2000),(server,status)->begin
if(status != 0)
error("Failed create server")
else
println("Client Connected")
client = TcpSocket()
client.readcb = (sock,args...)->begin
println("Read Callback")
spawn(`git status` > sock)
false #ignore unread buffer content
end
client.closecb = (args...)->begin
println("Client closed the connection")
end
accept(server,client)
Base.start_reading(client)
end
end)
Note that the second argument open_any_tcp_port is the connectioncb to be
set on the server.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment