Julio.jl is still work-in-progress.
API
Julio
Julio.Events
Julio.Lock
Julio.Promise
Julio.cancel!
Julio.channel
Julio.checkpoint
Julio.oncancel
Julio.open
Julio.queue
Julio.select
Julio.shield
Julio.spawn!
Julio.stack
Julio.withtaskgroup
Julio.withtimeout
Julio.yield
Julio.Events
— ConstantJulio.Events.f(args...; kwargs...)
Julio.Events.f(args...; kwargs...)
creates an event (i.e., an object describing how to execute f(args...; kwargs...)
) that can be passed to Julio.select
.
Example
Unlike (f, args...)
syntax that is also accepted by Julio.select
, Events.f(args...)
may have some states. For example, Events.sleep(seconds)
sets the timeout at the time the event is created and not when it is passed to Julio.select
:
julia> using Julio: Julio, Events
julia> Julio.withtaskgroup() do tg
Julio.spawn!(tg) do
ev = Events.sleep(0.1) # countdown starts now
while true
Julio.select(
ev => Returns(true), # eventually this event wins
Events.sleep(0) => Returns(false),
) && break
end
end
end;
Julio.Lock
— TypeJulio.Lock()
Creates a reentrant lock.
Julio.Promise
— TypeJulio.Promise{T}()
Julio.Promise()
Create a promise.
A value of type T
(or Any
if unspecified) can be set once by put!
. Calling fetch
blocks until put!
is called.
The indexing notation p[]
can be used as a synonym for put!
and fetch
.
Example
julia> using Julio
julia> p = Julio.Promise();
julia> p[] = 111;
julia> p[]
111
julia> Julio.withtaskgroup() do tg
p = Julio.Promise{Int}()
Julio.spawn!(tg) do
p[] = 222
end
p[]
end
222
Julio.cancel!
— FunctionJulio.cancel!(tg)
Julio.cancel!(scope)
Julio.cancel!(handle)
Cancel a task group tg
or cancellation scope scope
.
It can also be used for revoking the handle returned from Julio.oncancel
.
Julio.channel
— FunctionJulio.channel(T::Type = Any) -> (send_endpoint, receive_endpoint)
Julio.channel
creates a unbuffered channel and return a pair of send_endpoint
and receive_endpoint
.
Following methods are supported by the channel:
put!(send_endpoint, item::T)
Julio.tryput!(send_endpoint, item::T) -> success::Bool
take!(receive_endpoint) -> item::T
Julio.maybetake!(receive_endpoint) -> Some(item) or nothing
close(send_endpoint)
close(receive_endpoint)
Julio.checkpoint
— FunctionJulio.checkpoint()
Check for cancellation signal. It throws when cancellation is required.
Julio.oncancel
— FunctionJulio.oncancel(f, args...) -> handle
Register a cancellation callback f
and its arguments args
to the current cancellation scope. This callback is triggered via Julio.cancel!(tg)
or Julio.cancel!(scope)
.
The registered callback can be removed by Julio.cancel!(handle)
.
See also: Julio.cancel!
.
Example
julia> using Julio
julia> Julio.withtaskgroup() do tg
Julio.spawn!(tg) do
ch = Channel() # non Julio API
Julio.oncancel(close, ch) # close the channel on cancellation
try
take!(ch) # blocks forever
catch
isopen(ch) && rethrow() # ignore the exception due to `close`
end
end
Julio.cancel!(tg)
end;
Julio.open
— FunctionJulio.open(io::IO; close = false) -> wrapped_io::IO
Wrap an IO object into a new IO that is usable via Julio's synchronization API.
Julio.open(x::AbstractCommand, args...)
Julio.open(x::AbstractString, args...)
Synonym of Julio.open(open(x, args...); close = true)
.
Julio.open(f, x, args...)
A shorthand for
resource = Julio.open(x, args...)
try
f(resource)
finally
close(resource)
end
Julio.queue
— FunctionJulio.queue(T::Type = Any) -> (send_endpoint, receive_endpoint)
See Julio.channel
.
Julio.select
— FunctionJulio.select(ev₁, ev₂, ..., evₙ) -> ansᵢ
Select and execute one and only one event evᵢ
(1 ≤ i ≤ n
) and return its result ansᵢ
.
An even has the following format
(f, args...)
(f, args...) => g
Julio.Events.f(args...; kwargs...)
Julio.Events.f(args...; kwargs...) => g
where f
is a function such as take!
and put!
, args
are their arguments, kwargs
are the named arguments, and g
is a unary function that receives the output of (f, args...)
or Julio.Events.f(args...; kwargs...)
. If g
is not specified, identity
is used instead.
Examples
using Julio: Events
Julio.select(
(Julio.tryput!, send_endpoint, item),
(take!, receive_endpoint) => item -> begin
println("Got: ", item)
end,
Event.put!(another_send_endpoint, item),
Event.readline(io; keep = true) => line -> begin
println("Read line: ", line)
end,
)
Julio.shield
— FunctionJulio.shield(f)
Run f
in a special scope where the cancellation signals are blocked.
Julio.spawn!
— FunctionJulio.spawn!(f, tg, args...) -> task
Run a function f
with arguments args
inside a task managed by the task group tg
.
See Julio.withtaskgroup
.
Example
julia> using Julio
julia> send_endpoint, receive_endpoint = Julio.queue();
julia> Julio.withtaskgroup() do tg
Julio.spawn!(tg, 111) do x
put!(send_endpoint, x)
end
Julio.spawn!(tg) do
@show take!(receive_endpoint)
end
end;
take!(receive_endpoint) = 111
Julio.stack
— FunctionJulio.stack(T::Type = Any) -> (send_endpoint, receive_endpoint)
See Julio.channel
.
Julio.withtaskgroup
— FunctionJulio.withtaskgroup(f) -> ans
Create a task group tg
and pass it to the function f
of the form tg -> ans
.
See Julio.spawn!
.
Example
julia> using Julio
julia> Julio.withtaskgroup() do tg
Julio.spawn!(tg) do
println("hello")
end
end;
hello
Julio.withtimeout
— FunctionJulio.withtimeout(f, seconds) -> Some(ans) or nothing
Run f()
with timeout seconds
. If it finishes with output value ans
before the timeout, return Some(ans)
. Return nothing
otherwise.
Note that blocking operations must use Julio API for automatic cancellation; Julio.sleep
instead of sleep
, read(Julio.open(io))
instead of read(io)
, and so on. Use Julio.
Non-Julio API can be cancelled using Julio.oncancel
.
Example
julia> using Julio
julia> Julio.withtimeout(0.1) do
Julio.sleep(60)
end === nothing # too slow
true
julia> Julio.withtimeout(60) do
Julio.sleep(0.1)
end === Some(nothing) # success
true
Julio.yield
— FunctionJulio.yield()
A shorthand for Julio.checkpoint(); yield()
.