Note

Julio.jl is still work-in-progress.

API

Julio.EventsConstant
Julio.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;
source
Julio.PromiseType
Julio.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
source
Julio.cancel!Function
Julio.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.

source
Julio.channelFunction
Julio.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)
source
Julio.checkpointFunction
Julio.checkpoint()

Check for cancellation signal. It throws when cancellation is required.

source
Julio.oncancelFunction
Julio.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;
source
Julio.openFunction
Julio.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
source
Julio.selectFunction
Julio.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,
)
source
Julio.shieldFunction
Julio.shield(f)

Run f in a special scope where the cancellation signals are blocked.

source
Julio.spawn!Function
Julio.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
source
Julio.withtaskgroupFunction
Julio.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
source
Julio.withtimeoutFunction
Julio.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
source
Julio.yieldFunction
Julio.yield()

A shorthand for Julio.checkpoint(); yield().

source