Air.jl

Air.TX_MAX_ATTEMPTSConstant
TX_MAX_ATTEMPTS

The maximum number of retry attempts that a transaction will make before aborting the transaction.

Air.airoutConstant
airout

The airout object is a AirOut object that wraps the stdout object.

See also: AirOut

Air.current_txConstant
current_tx

The current_tx constant is a Var{T} that stores the current task's running Transaction, or nothing if there is no transaction running.

See also: currtx

Air.AbstractPArrayType
AbstractPArray{T,N}

The Abstract persistent array type represents any Array-like type that is persistent. The Air library provides the reified type PArray{T,N}.

See also: PArray, PVector.

Air.ActorType
Actor{T}

An actor is an object that represents a worker-thread to which tasks can be scheduled. Any scheduled function is guaranteed to be evaluated at some point in the future in some other thread, and the return value of that function will become the new value held by the actor. Each function, when it is run, is passed the actor's value as one of its argument.

Like with Refs, you can access an actor's current value using getindex, e.g., actor[]. Within a transaction, this will be guaranteed to remain fixed for the duration of the transaction; outside of a transaction, this may change at arbitrary times.

Actors may be initialized with post-processing functions. These functions are called immediately after executing any scheduled function and are given as their first argument the original actor value and as their second argument the return value of the scheduled function. Instead of saving this return value, the return value of the post-processing function is saved in the actor. This is useful for actors whose job is, for example, to serialize output to a log file being written to across many threads. If we run something like send(println, log_actor, "Some log message") the println function will return nothing, which we would like to convert back into the log stream so that subsequent send calls can continue to use the println fuction.

Actors may additionally be given an error handler. Whenever an exception occurs during a scheduled function, the error handler will be called with the arguments of (1) the actor object, (2) the current actor value, and (3) the exception that was caught. When an error has occurred, any attempt to schedule a function to the actor or to read from the actor will cause an exception to be raised. The error may be examined using geterror(actor) and restarted using reset(actor).

All fields in an actor object should be considered strictly private. These fields are likely to change between releases, and changing the values will break your code.

See also: tx, @tx, send, geterror, reset.

Examples

DocTestSetup = quote
    using Air
end
julia> a = Actor{Symbol}(:start_sym)
Actor{Symbol}(@JIm7aUS2sOl: :start_sym)

julia> send(a) do val; sleep(0.1); Symbol("new_$(val)") end
Actor{Symbol}(@JIm7aUS2sOl: :start_sym)

julia> sleep(1); a[]
:new_start_sym
Air.ActorExceptionType
ActorException{T}(error, value, argno, args)

An ActorException object is thrown whenever one attempts to obtain the value of or send a function to an actor that is in an error state. An error state occurs when an unhandled exception is raised while an actor is processing a sent function. In such a case the geterror() and restart() functions may be used. The geterror() function yields an ActorException object in which the exception that was raised is stored as error, the value of the actor when the send was run is stored in value, and the args and argno give the full contex of the send call (i.e., the fucntion followed by the arguments is args and the argument number that corresponds to the actor is argno).

See also: Actor, geterror, reset, send

Air.ActorMsgType
ActorMsg

A message, queued for an Actor via the send() function.

The ActorMsg struct is considered part of Air's private/internal implementation details.

Air.ActorTxDataType
ActorTxData{T}

The data tracked for an Actor{T} during a transaction by the transaction's Transaction struct.

The ActorTxData struct is considered part of the internal/private code of Air and generally should not be used outside of the Air library.

Air.AirOutType
AirOut

The AirOut type is a derivative of the IO class and is intended for handling output to stdout across multiple threads in a thread-safe way. It is similar TxIO except that it only writes to stdout and is only really intended for use with the airout object.

See also: Actor, airout, TxIO

Air.DelayType
Delay{T}

Delay objects can be used to lazily calculate a single value the first time it is requested. They act like Refs in that you access a delay d via d[]. Delay objects are thread-safe and are functionally immutable.

See also: @delay, LazyDict

Examples

DocTestSetup = quote
    using Air
end
julia> # Create a Delay with a long run time.
       d = Delay{Int64}(() -> (println("Running."); sleep(2); 10))
Delay{Int64}(<...>)

julia> # Start a few threads, each of which attempt to read it. The function
       # will only run once.
       for th in [(Threads.@spawn d[]) for _ in 1:5]; wait(th) end
Running.

julia> # Ensure that it produced the correct value and doesn't run again.
       d[]
10
Air.LazyDictType
LazyDict{K,V}

A dictionay type equivalent to PDict{K,V} in every way except that for any value in the dict that is a Delay object, the dictionary hides the delay and always returns the delay's value. This allows any value that has not yet been requested to be lazily unevaluated.

See also: PDict, Base.Dict, LazyIdDict, Delay, @delay.

Examples

DocTestSetup = quote
    using Air
end
julia> LazyDict()
LazyDict{Any,Any}()
julia> LazyDict(:a => 1, :b => 2, :c => 12.8)
LazyDict{Symbol,Real} with 3 entries:
  :c => 12.8
  :a => 1
  :b => 2
julia> d = LazyDict{Symbol,Float64}(:a => 1, :b => 2, :c => 12.8)
LazyDict{Symbol,Float64} with 3 entries:
  :c => 12.8
  :a => 1.0
  :b => 2.0

julia> d2 = push(d, :d => Delay{Real}(() -> (println("Running..."); 0.5))); haskey(d2, :d)
true

julia> d2[:d]
Running...
0.5

julia> d2[:d]
0.5
Air.LazyIdDictType
LazyIdDict{K,V}

A dictionay type equivalent to PIdDict{K,V} in every way except that for any value in the dict that is a Delay object, the dictionary hides the delay and always returns the delay's value. This allows any value that has not yet been requested to be lazily unevaluated.

See also: PIdDict, Base.IdDict, LazyDict, Delay, @delay.

Examples

DocTestSetup = quote
    using Air
end
julia> LazyIdDict()
LazyIdDict{Any,Any}()
julia> LazyIdDict(:a => 1, :b => 2, :c => 12.8)
LazyIdDict{Symbol,Real} with 3 entries:
  :b => 2
  :a => 1
  :c => 12.8

```jldoctest; filter=r"LazyIdDict{Symbol, ?Float64} with 3 entries:" julia> d = LazyIdDict{Symbol,Float64}(:a => 1, :b => 2, :c => 12.8) LazyIdDict{Symbol,Float64} with 3 entries: :c => 12.8 :a => 1.0 :b => 2.0

julia> d2 = push(d, :d => Delay{Real}(() -> (println("Running..."); 0.5))); haskey(d2, :d) true

julia> d2[:d] Running... 0.5

julia> d2[:d] 0.5

Air.PArrayType
PArray{T,N}

The PArray type is a persistent/immutable corrolary to the Array{T,N} type. Like Array, PArray can store n-dimensional non-ragged arrays. However, unlike Arrays, PArrays can create duplicates of themselves with finite edits in log-time.

PArrays have a similar interface as Arrays, but instead of the functions push!, pop!, and setindex!, PArrays use push, pop, and setindex. PArrays also have efficient implementations of pushfirst and popfirst.

Examples

DocTestSetup = quote
    using Air
end
julia> PArray()
0-element PArray{Any,1}
julia> u = PArray{Int,1}([1,2])
2-element PArray{Int64,1}:
 1
 2

julia> push(u, 3)
3-element PArray{Int64,1}:
 1
 2
 3

julia> PArray{Symbol,2}(:abc, (2,3))
2×3 PArray{Symbol,2}:
 :abc  :abc  :abc
 :abc  :abc  :abc
Air.PDictType
PDict{K,V}

A dictionay type roughly equivalent to Dict{K,V} but that stores data using a persistent hash array mapped trie system that allows for efficient persistent operations. These operations are represented by non-mutating versions of the standard dictionary functions, such as setindex in place of setindex!, push in place of push!, and pop in place of pop!. These operations are performed in O(log n) time, and minimal data duplication is performed in update operations.

See also: PIdDict, Dict, push, pop, setindex, delete, insert, getpair.

Examples

DocTestSetup = quote
    using Air
end
julia> PDict()
PDict{Any,Any}()
julia> PDict(:a => 1, :b => 2, :c => 12.8)
PDict{Symbol,Real} with 3 entries:
  :c => 12.8
  :a => 1
  :b => 2
julia> d = PDict{Symbol,Float64}(:a => 1, :b => 2, :c => 12.8)
PDict{Symbol,Float64} with 3 entries:
  :c => 12.8
  :a => 1.0
  :b => 2.0

julia> :b in keys(d)
true

julia> d[:c]
12.8

julia> push(d, :d => 0.1)
PDict{Symbol,Float64} with 4 entries:
  :d => 0.1
  :c => 12.8
  :a => 1.0
  :b => 2.0
Air.PHeapType
PHeap{T,W,F}

A PHeap object is a priority queue to which objects can be pushed and given a particular weight. PHeaps can then be iterated in weighted order, popped in weighted order, and the first element may be obtained in weighted order. Additionally, a random sample may be drawn from a heap, which uses the distribution implied by the relative weights of the items in the heap.

PHeap objects may be initialized with a single argument of type F <: Function, in which case this function is used to compare the weights for ordering. By default this is > such that high weights are retrieved first by the first() function and removed first by the pop() function. Note, however, that the relative weights are still used by the rand function regardless of the ordering function, so negative values cannot be used.

See also: PWSet, PWDict, pop, Base.first.

Air.PIdDictType
PIdDict{K,V}

A dictionay type roughly equivalent to IdDict{K,V} but that stores data using a persistent hash array mapped trie system that allows for efficient persistent operations. These operations are represented by non-mutating versions of the standard dictionary functions, such as setindex in place of setindex!, push in place of push!, and pop in place of pop!. These operations are performed in O(log n) time, and minimal data duplication is performed in update operations.

See also: PDict, Base.IdDict, push, pop, setindex, delete, insert, getpair.

Examples

DocTestSetup = quote
    using Air
end
julia> PIdDict()
PIdDict{Any,Any}()

jldoctest; filter=r"PIdDict{Symbol, ?Real} with 3 entries:" julia> PIdDict(:a => 1, :b => 2, :c => 12.8) PIdDict{Symbol,Real} with 3 entries: :c => 12.8 :a => 1 :b => 2

jldoctest; filter=r"PIdDict{Symbol, ?Float64} with [34] entries:" julia> d = PIdDict{Symbol,Float64}(:a => 1, :b => 2, :c => 12.8) PIdDict{Symbol,Float64} with 3 entries: :c => 12.8 :a => 1.0 :b => 2.0

julia> :b in keys(d) true

julia> d[:c] 12.8

julia> push(d, :d => 0.1) PIdDict{Symbol,Float64} with 4 entries: :d => 0.1 :c => 12.8 :a => 1.0 :b => 2.0

Air.PIdLinearDictType
PIdLinearDict{K,V}

An identity-based persistent dict type that uses a simple array representation internally; accordingly PIdLinearDict does not peform persistent operations such as setindex, push, and delete efficiently. It is intended to be used by Air internally as a sub-dict that stores items whose hash values are identical.

See also: PLinearDict, PIdDict.

Air.PIdLinearSetType
PIdLinearSet{T}

A persistent IdSet type that uses a simple array representation internally; accordingly PIdLinearSet does not peform persistent operations such as setindex, push, and delete efficiently. It is intended to be used by Air internally as a set that stores items whose hash values are identical.

See also: PLinearSet, PSet.

Air.PIdSetType
PIdSet{T}

A persistent identity-based set type that uses an array hash-mapped trie structure to allow for efficient updating of the set using the persistent operations defined by Air such as push, and delete.

See also: Set, PIdSet.

Examples

DocTestSetup = quote
    using Air
end
julia> PIdSet()
PIdSet{Any}()

julia> :a in PIdSet([:a, :b, :c])
true

julia> :d in PIdSet([:a, :b, :c])
false

julia> :d in push(PIdSet(), :d)
true
Air.PLinearDictType
PLinearDict{K,V}

A persistent dict type that uses a simple array representation internally; accordingly PLinearDict does not peform persistent operations such as setindex, push, and delete efficiently. It is intended to be used by Air internally as a sub-dict that stores items whose hash values are identical.

See also: PIdLinearDict, PDict.

Air.PLinearSetType
PLinearSet{T}

A persistent set type that uses a simple array representation internally; accordingly PLinearSet does not peform persistent operations such as setindex, push, and delete efficiently. It is intended to be used by Air internally as a set that stores items whose hash values are identical.

See also: PIdLinearSet, PSet.

Air.PMatrixType
PMatrix{T}

An alias for PArray{T,2}, representing a persistent matrix.

Air.PSetType
PSet{T}

A persistent set type that uses an array hash-mapped trie structure to allow for efficient updating of the set using the persistent operations defined by Air such as setindex, push, and delete.

See also: Set, PIdSet.

Examples

DocTestSetup = quote
    using Air
end
julia> PSet()
PSet{Any}()

julia> :a in PSet([:a, :b, :c])
true

julia> :d in PSet([:a, :b, :c])
false

julia> :d in push(PSet(), :d)
true
Air.PTreeType
PTree{T}

PTree is a persistent tree/array hybrid that maps arbitrary unsigned integers (type HASH_T) to values. It can efficiently be used for arrays or for hash-maps, and supports efficient lookup, association, and dissociation.

All fields of a PTree should be considered strictly private, as modification of the fields may result in a kernel crash. The properties of a PTree are both immutable and safe to inpect.

Air.PVectorType
PVector{T}

An alias for PArray{T,1}, representing a persistent vector.

Air.PWDictType
PWDict{K,V}

A persistent dictionary with weighted pairs. As such, a PWDict supports the typical operations of a PDict as well as the following:

  • The first function yields the key-value pair with the highest weight.
  • The pop function yields a copy of the dictionary without the pair that has the highest weight.
  • Iteration occurs in the order of greatest to least weight.
  • The weights can be changed with the getweight and setweight functions; setweight yields a duplicate dictionary with updated weights.

See also: PDict, getweight, setweight.

Examples

DocTestSetup = quote
    using Air
end
julia> PWDict{Symbol,Int}(:a => (1,0.1), :b => (2, 0.2), :c => (3, 0.3))
PWDict{Symbol,Int64,Float64} with 3 entries:
  :c => 3
  :b => 2
  :a => 1
Air.PWIdDictType
PWIdDict{K,V}

A persistent dictionary with weighted pairs. As such, a PWIdDict supports the typical operations of a PIdDict as well as the following:

  • The first function yields the key-value pair with the highest weight.
  • The pop function yields a copy of the dictionary without the pair that has the highest weight.
  • Iteration occurs in the order of greatest to least weight.
  • The weights can be changed with the getweight and setweight functions; setweight yields a duplicate dictionary with updated weights.

See also: PIdDict, PWDict, getweight, setweight.

Examples

DocTestSetup = quote
    using Air
end
julia> PWIdDict{Symbol,Int}(:a => (1,0.1), :b => (2, 0.2), :c => (3, 0.3))
PWIdDict{Symbol,Int64,Float64} with 3 entries:
  :c => 3
  :b => 2
  :a => 1
Air.PWIdSetType
PWIdSet{T}

A persistent set with weighted elements. As such, a PWIdSet supports the typical operations of a PIdSet as well as the following:

  • The first function yields the element with the highest weight.
  • The pop function yields a copy of the set without the element that has the highest weight.
  • Iteration occurs in the order of greatest to least weight.
  • The weights can be changed with the getweight and setweight functions; setweight yields a duplicate dictionary with updated weights.

See also: PIdSet, PWSet, getweight, setweight.

Examples

DocTestSetup = quote
    using Air
end
julia> PWIdSet{Symbol}(:a => 0.1, :b => 0.2, :c => 0.3)
PWIdSet{Symbol,Float64} with 3 elements:
  :c
  :b
  :a
Air.PWSetType
PWSet{K,V}

A persistent set with weighted elements. As such, a PWSet supports the typical operations of a PSet as well as the following:

  • The first function yields the element with the highest weight.
  • The pop function yields a copy of the set without the element that has the highest weight.
  • Iteration occurs in the order of greatest to least weight.
  • The weights can be changed with the getweight and setweight functions; setweight yields a duplicate dictionary with updated weights.

See also: PSet, getweight, setweight.

Examples

DocTestSetup = quote
    using Air
end
julia> PWSet{Symbol}(:a => 0.1, :b => 0.2, :c => 0.3)
PWSet{Symbol,Float64} with 3 elements:
  :c
  :b
  :a
Air.PromiseType
Promise{T}

Promise objects represent placeholders for values that may or may not have been delivered yet. This is effectively a Channel object that can only be put! to a single time and all take calls on the promise will return that value. Promise values can be accessed via the take() function (not the take!() function) or via p[] for promise p. In both cases, the running thread is suspended until a value is delivered.

Examples

DocTestSetup = quote
    using Air
end
julia> p = Promise{Symbol}()
Promise{Symbol}(<...>)

julia> isready(p)
false

julia> put!(p, :value)
:value

julia> isready(p)
true

julia> take(p)
:value

julia> p[]
:value
Air.ReentrantRefType
ReentrantRef{T}

A ReentrantRef is a type of ref object that is thread-safe. There are a few strategies for this, each of which are encoded in a different object type that inheits from ReentrantRef. These types are as follows.

Var: Var objects act like Ref objects except that changes to them are exclusively task-local and must be performed in specific scoped expressions. However, the state of all Var objects for the current task can also be saved and restored at a later point.

Actor: Actor objects obey the actor pattern; you can call send(fn, actor, args...) where fn is a function that is, in another thread at some point, called as fn(actor[], args...). The new value of the actor after running fn is the return value of the call.

Volatile: Volatile objects are Refs that can be changed by any thread but that must be changed only within a synchronized transaction that ensures that all reads and writes of volatiles, as well as reads from and sends to actors, are atomic: either they all happen successfully, or none of them do.

Air.TransactionType
Transaction

A transaction object keeps track of what is going on during a particular transaction. These are generally low-level objects that shouldn't be touched directly.

Transactions have the following propertiies:

  • state is either :running, :validating, or :error;
  • rvolatiles is the set of all Volatile objects that have been read during the transaction;
  • wvolatiles is the set of all Volatile objects that have been changed;
  • actors is the set of all Actor objects to which messagees have been sent during the transaction; and
  • sources is the set of all Source objects from which items have been popped.
Air.TransactionalRefType
TransactionalRef{T}

A TransactionalRef is a reentrant reference that additional participates in transactions. Transactional refs include Actors and Volatiles.

Air.TxIOType
TxIO

The TxIO type is a derivative of the IO class and is intended for handling output to streams across multiple threads in a thread-safe way. TxIO objects can be constructed from IO objects and can be printed/written to like normal IO objects. However, all output is performed in a separate asynchronous thread, and writes that occur during a transaction always occur only if the transaction succeeds.

See also: Actor, airout

Air.TxRetryExceptionType
TxRetryException

A TxRetryException is throws when a transaction needs to be retried but an error hasn't necessarily been generated otherwise. This can be thrown during a transaction to restart the transaction; though doing this can easily lead to infinite loops.

Air.VarType
Var{T}

A Var object represents a task-local piece of data with a default value. You can access a Var with the getindex function (var[]) and you can set it with the setindex! function (var[] = newval). However, the new assignment will always be task-local only. Because of this, Vars are safe to access and update in a multi-threaded program.

All fields of a Var should be considered strictly private.

See also: @var, ReentrantRef, vars, withvars, wrapsetvars, wrapwithvars, Threads.current_task, Threads.task_local_storage.

Examples

DocTestSetup = quote
    using Air
end
julia> v = Var{Symbol}(:start_sym)
Var{Symbol}(@JIm7aUS2sOl: :start_sym; init=:start_sym)

julia> v[]
:start_sym

julia> withvars(v => :new_sym) do; v[] end
:new_sym

julia> withvars(v => :new_sym) do; fetch(Threads.@spawn v[]) end
:start_sym

julia> v[]
:start_sym
Air.VarsDictType
VarsDict

The type of a dictionary of Var bindings, as returned by the function vars() and as is required by the function setvars().

Air.VolatileType
Volatile{T}(value)
Volatile{T}(value, filter_fn)
Volatile{T}(value, filter_fn, finalize_fn)

Volatile objects are Ref objects that must be used in conjunction with transaction blocks (see @tx and tx). The value of a Volatile can be accessed at any time, and there is no particular guarantee that a Volatile's value won't be changed by another thread outside of a transaction, thus reading them outside of a transaction can potentially create race conditions. Critically, Volatile objects can only be set inside of a transaction, and, within a transaction, a Volatile's value is guaranteed to be constant. In other words, Volatile objects are Ref objects that behave as if they are locked for the executing thread whenever that thread is inside a transaction block.

The arguments filter_fn and finnalize_fn are functions for making sure that the value of a volatile conforms to some standard. The two functions are similar but are intended for slightly different use cases:

  • filter_fn is called every time the value of a volatile is set. The value saved in the volatile is filter_fn(value) instead of value itself. Values are only filtered when the volatile is set directly (vol[] = value)–-the filter is not rerun when the filter_fn is changed (via setfilter!) nor when the finalize_fn returns a value.
  • finalize_fn is called with the volatile's value immediately after the body of the transaction has completed, but before a commit is attempted. The finalize_fn function acts like the filter_fn in that finalize_fn(value) replaces value in the volatile.

Both filter_fn and finalize_fn can throw exceptions, which will abort the running transaction.

For a Volatilev, one may set v's stored value via v[] = value. This must be done inside a transaction (via tx or @tx). To change the filter or the finalize functions, use the setfilter! and setfinalize! functions, both of which also must be run in transactions as well.

See also: tx, @tx, setfilter!, setfinalize!.

Examples

DocTestSetup = quote
    using Air
end
julia> v = Volatile{Symbol}(:startval)
Volatile{Symbol}(@JIm7aUS2sOl: :startval)

julia> @tx v[] = :newval
:newval

julia> v[]
:newval
Air.actor_mainMethod
actor_main(actor)

The actor main function is what actually manages everything behind the scenes in the actor tasks. Note that this function and the task/thread it is running in is the only place that the actor's value can be legally changed. Changing the value anywhere else can result in undefined behavior. The actor's condition should never change.

This function is designed to process all the messages in an actor's queue then to return. When a new thread wants to enqueue a message to an actor that has an empty queue, that thread must spin up the actor_main function to process the items in the queue (this is done by the send function automatically).

This function is part of Air's internal/private implementation details.

Air.actor_reset!Method
actor_reset!(actor, val)

Resets the given actor to have the given value. If the actor is not in an error state, yields nothing and does nothing. Otherwise, yields the ActorExcption object that was cleared. It is required that the actor's mutex be held at ths time this function is called.

This function is considered part of Air's internal/private implementation details.

Air.actor_resetMethod
actor_reset(a, s)

If the given Actor object a is in an error state, this function resets the actor to have the new value s then yields the ActorException object that was just cleared. If a is not in an error state, this function simply yields nothing.

This function is considered part of the internal/private interface of Air and shouldn't generally be called outside of it.

Air.actor_send!Method
actor_send!(actor, message)

Enqueues the given message to the given actor and starts the actor's task, if necessary. This function requires that the actor's condition be held. Yields the actor.

This function is considered part of Air's internal/private implementation details.

Air.actor_sendMethod
actor_send(a, msg)

Adds the given ActorMsg message object msg to the queue of the given Actor object a such that it will be processed in a separate thread. Yields nothing.

This function is considered part of the internal/private interface of Air and shouldn't generally be called outside of it.

Air.actor_start!Method
actor_start!(actor)

If the given Actor object is not in an error state, is not running, and does not have an empty queue, then actor_start!(actor) will start actor's processing task. This should only be called by send! when the first message to an empty queue is finalized.

If either the actor is already running or the task is successfully started, then that task is yielded. If the actor has an empty queue, then nothing is returned, and if the actor is in an error state, then an exception is thrown.

Note: It is required that the mutx for the given actor be held when this function is called; otherwise race conditions could be inadvertantely created. The actor_start method locks the actor's mutex then calls this function. Both methods are private to Air and should not generally be used outside of it.

This function is considered part of Air's internal/private implementation details.

Air.actor_startMethod
actor_start(actor)

If the given Actor object is not in an error state, is not running, and does not have an empty queue, actor_start(actor) will start actor's processing task. This should only be called by send! when the first message to an empty queue is finalized.

If either the actor is already running or the task is successfully started, then that task is yielded. If the actor has an empty queue, then nothing is returned, and if the actor is in an error state, then an exception is thrown.

This function is considered part of Air's internal/private implementation details.

Air.actor_valueMethod
actor_value(a)

Yields the in-transaction value for the given Actor object a if there is a running transaction; otherwise yields the current out-of-transaction value of a.

This function is considered part of the internal/private interface of Air and shouldn't generally be called outside of it.

Air.currtxMethod
currtx()

Yields the current Transaction object, or nothing if there is no transaction running in the current task.

See also: Transaction

Examples

DocTestSetup = quote
    using Air
end
julia> currtx() === nothing
true

julia> @tx (currtx() === nothing)
false
Air.deleteMethod
delete(coll, k)

Yields a copy of the collection coll with the item associated with the given index or key k deleted. This function works on dictionaries, vectors, tuples, and sets, and it always yields a copy of the collection without modifying its aguments. For the persistent collections defined in Air, this is efficient, but for most mutable objects, this is O(n).

See also: Base.delete!, insert, pop.

Examples

DocTestSetup = quote
    using Air
end
julia> delete((:a,:b,:c,:d), 2)
(:a, :c, :d)
julia> u = [:a,:b,:c,:d]; delete(u, 1)
3-element Array{Symbol,1}:
 :b
 :c
 :d
julia> s1 = Set([:a,:b,:c,:d]); s2 = delete(s1, :d); (:d in s1, :d in s2)
(true, false)
julia> b = BitArray([0,0,0,1,0]); delete(b, 4)
4-element BitArray{1}:
 0
 0
 0
 0

julia> b[2]
false
Air.depth_to_bitshiftMethod
depth_to_bitshift(depth)

Yields the tuple (B0,S) of the first bit index and the shift for the given depth.

Air.equalfnMethod
equalfn(x)

If x is an object (such as a PSet or Dict) that has an opinion about equality, equalfn(x) returns the function that it uses.

See also: hashfn

Examples

DocTestSetup = quote
    using Air
end
julia> equalfn(Dict) == isequal
true

julia> equalfn(IdDict) == (===)
true

julia> equalfn(PSet) == isequal
true

julia> equalfn(PArray)
ERROR: ArgumentError: no equalfn for type PArray
Air.geterrorMethod
geterror(actor)

If the given Actor object is currently in an error state, then yields the ActorException object that describes the error. Otherwise, yields nothing.

See also: Actor, reset, send

Examples

DocTestSetup = quote
    using Air
end
julia> a = Actor{Symbol}(:start_sym)
Actor{Symbol}(@JIm7aUS2sOl: :start_sym)

julia> geterror(a) === nothing
true

julia> send(a) do val; error("test") end
Actor{Symbol}(@JIm7aUS2sOl: :start_sym)

julia> sleep(1); a
Actor{Symbol}(@JIm7aUS2sOl: --error--)

julia> geterror(a) isa ActorException
true
Air.getfilterMethod
getfilter(v)

Yields the filter-function for the volatile v.

Air.getfinalizeMethod
getfinalize(v)

Yields the finalize-function for the volatile v.

Air.getpairFunction
getpair(d, k)

If the key k is found in the dictionary d, yields the pair (k => d[k]); otherwise yields missing.

See also: Base.get, Base.getindex.

Examples

DocTestSetup = quote
    using Air
end
julia> d = Dict(:a => 1, :b => 2, :c => 3); getpair(d, :a)
:a => 1

julia> getpair(d, :x)
missing
Air.getweightMethod
getweight(h, x)

Yields the weight for the given value x in the given persistent heap or persistent weighted collection h. If h is a weighted dictionary, then x should be the key.

If the key or object x is not found in the collection h, then 0 is returned.

See also: setweight, PWDict, PWSet.

Examples

DocTestSetup = quote
    using Air
end
julia> d = PWSet{Symbol}(:a => 1.0, :b => 2.0, :c => 3.0)
PWSet{Symbol,Float64} with 3 elements:
  :c
  :b
  :a

julia> getweight(d, :a)
1.0
Air.hashfnMethod
hashfn(x)

If x is an object (such as a PSet or Dict) that has an opinion about how it hashes objects, hashfn(x) returns the function that it uses. It is sufficient in almost all circumstances to define equalfn(T); the hashfn should always match the equalfn regardless.

See also: equalfn

Examples

DocTestSetup = quote
    using Air
end
julia> hashfn(Dict) == hash
true

julia> hashfn(IdDict) == objectid
true

julia> hashfn(PSet) == hash
true

julia> hashfn(PArray)
ERROR: ArgumentError: no equalfn for type PArray
Air.highmaskMethod
highmask(bitno, T)
highmask(bitno)

Yields a mask of (unsigned integer) type T with all bits above the given bit number set to true and all bits below that number set to false. The bit itself is set to true. Bits are indexed starting at 0.

The default value of T is the PTree hash type (HASH_T).

highmask(bitno) is equal to ~lowmask(bitno).

Air.insertFunction
insert(coll, idx, val)

Yields a copy of the given collection coll with the given value cal inserted at the given index. Roughly equivalent to insert!(copy(arr), idx, va): the insert function never modifies its arguments and always yields a copy. For the persistent collections defined in Air, this operation is efficient, but for most mutable objects, this is O(n).

See also: Base.insert!, push, delete.

Examples

DocTestSetup = quote
    using Air
end
julia> insert((:a,:b,:c,:d), 2, :x)
(:a, :x, :b, :c, :d)
julia> u = [:a,:b,:c,:d]; insert(u, 1, :x)
5-element Array{Symbol,1}:
 :x
 :a
 :b
 :c
 :d

julia> length(u)
4
julia> b = BitArray([0,0,0,0]); insert(b, 2, 1)
5-element BitArray{1}:
 0
 1
 0
 0
 0

julia> b[2]
false
Air.lockallFunction
lockall(f, l1, l2, ...)

Locks all of the lockable objects l1, l2, etc. then runs f, unlocks the objects, and returns the return value of f().

See also: Threads.ReentrantLock

Examples

DocTestSetup = quote
    using Air
end
julia> (r1, r2, r3) = [ReentrantLock() for _ in 1:3]
       lockall(r1, r2, r3) do; :success end
:success

julia> lockall([r1, r2, r3]) do; :success end
:success

julia> lockall((r1, r2, r3)) do; :success end
:success
Air.lowmaskMethod
lowmask(bitno, T)
lowmask(bitno)

Yields a mask of (unsigned integer) type T with all bits above the given bit number set to false and all bits below that number set to true. The bit itself is set to false. Bits are indexed starting at 0.

The default value of T is the PTree hash type (HASH_T).

lowmask(bitno) is equal to ~highmask(bitno).

Air.pfillMethod
pfill(val, dims...)

Yields a persistent array (PArray) of values exactly as done by the fill() function.

See also pones, pzeros, fiill

Examples

DocTestSetup = quote
    using Air, SparseArrays
end
julia> pfill(NaN, 3)
3-element PArray{Float64,1}:
 NaN
 NaN
 NaN

julia> pfill(:abc, 2, 3)
2×3 PArray{Symbol,2}:
 :abc  :abc  :abc
 :abc  :abc  :abc
Air.ponesMethod
pones(dims...)
pones(T, dims...)

Yields a persistent array (PArray) of ones exactly as done by the ones() function.

See also pzeros, pfill, ones

Examples

DocTestSetup = quote
    using Air, SparseArrays
end
julia> pones(Integer, 3)
3-element PArray{Integer,1}:
 1
 1
 1

julia> pones(Bool, (1,2))
1×2 PArray{Bool,2}:
 1  1

julia> pones(2, 3)
2×3 PArray{Float64,2}:
 1.0  1.0  1.0
 1.0  1.0  1.0

julia> pones((1, 1, 1, 1))
1×1×1×1 PArray{Float64,4}:
[:, :, 1, 1] =
 1.0
Air.popFunction
pop(coll)

Yields a tuple (last, most) where last is the last element of the given collection and most is a duplicate tuple of all but the last element of tup. This is basically a persistent equivalent to the pop! function that never modifies the given coll. For persistent collections in Air, these operations are efficient, but for most mutable types, it is O(n).

pop(coll, key[, default])

Similar to pop!, pops the specific key from the given collection coll and yields (val, rest) where val is the value associated with key in coll and rest is the remainder of the collection without key. If the key is not in coll, then default is yielded or an error is thrown.

See also: Base.pop!, push, popat, delete.

Examples

DocTestSetup = quote
    using Air
end
julia> pop((:a,:b,:c,:d))
(:d, (:a, :b, :c))

julia> u = [:a,:b,:c,:d]; pop(u)
(:d, [:a, :b, :c])

julia> length(u)
4

julia> s = Set([:a, :b, :c]); pop(s, :c)
(:c, Set([:a, :b]))

julia> :c in s
true
julia> d = Dict(:a => 1, :b => 2, :c => 3); pop(d, :c)
(3, Dict(:a => 1,:b => 2))

julia> d[:c]
3
Air.popatFunction
popat(coll, k)

Yields a tuple (el, rest) where el is the kth element of the given collection coll and rest is a duplicate of all but the kth element of coll. This is basically a persistent equivalent to the popat! function that never modifies the given coll. For persistent collections in Air, these operations are efficient, but for most mutable types, it is O(n).

See also: Base.popat!, pop, popfirst, delete.

Examples

DocTestSetup = quote
    using Air
end
julia> popat((:a,:b,:c,:d), 2)
(:b, (:a, :c, :d))

julia> u = [:a,:b,:c,:d]; popat(u, 3)
(:c, [:a, :b, :d])

julia> length(u)
4
Air.popfirstFunction
popfirst(coll)

Yields a tuple (first, rest) where first is the first element of the given collection and rest is a duplicate tuple of all but the first element of tup. This is basically a persistent equivalent to the popfirst! function that never modifies the given coll. For persistent collections in Air, these operations are efficient, but for most mutable types, it is O(n).

See also: Base.popfirst!, pushfirst, popat, delete.

Examples

DocTestSetup = quote
    using Air
end
julia> popfirst((:a,:b,:c,:d))
(:a, (:b, :c, :d))

julia> u = [:a,:b,:c,:d]; popfirst(u)
(:a, [:b, :c, :d])

julia> length(u)
4
Air.ptree_bitshiftMethod
ptree_bitshift(nodeid)

Yields the bitshift for the given ptree node id.

Air.ptree_cellindex!Method
ptree_cellindex!(ptree, leafid)
ptree_cellindex!(nodeid, bits, leafid)

Yields the index into the ptree's cell vector of the child containing the leaf with the given id. If the ptree does not contain the given leafid because the appropriate bit is not set then 0 is returned. However, unlike the function ptree_cellindex(), this function does not check whether or not the given leafid is in the set of possible children of the tree.

Air.ptree_cellindexMethod
ptree_cellindex(ptree, leafid)
ptree_cellindex(nodeid, bits, leafid)

Yields a tuple (present, bitindex, cellindex) in which [1] present is a boolean indicating whether a ptree containing the given leafid or the leaf itself is a child of the given ptree; [2] bitindex is the index into ptree's bits integer for the given leaf, and cellindex is the inndex innto the ptree's cell array where that child is or would be found. If the leafid is outside of the given ptree (i.e., it cannot exist beneath this ptree) then the cellindex returned returned is 0, but the bitindex will still match the appropriate shift for the ptree's depth.

Air.ptree_cellkeyMethod
ptree_cellkey(ptree, childidx)

Yields the leafid (a HASH_T value) of the key that goes with the particular child index that is given. This only works correctly for twig nodes.

Air.ptree_depthMethod
ptree_depth(nodeaddr)

Yields the depth of the node with the given node address. This depth is in the theoretical complete tree, not in the reified tree represented with memory.

Air.ptree_firstbitMethod
ptree_firstbit(nodeid)

Yields the first-bit for the given ptree node id.

Air.ptree_highbitdiffMethod
ptree_highbitdiff(id1, id2)

Yields the highest bit that is different between id1 and id2.

Air.ptree_idMethod
ptree_id(minleaf, depth)

Yields the node-id for the node whose minimum leaf and depth are given.

Air.ptree_isbeneathMethod
ptree_isbeneath(nodeid, leafid)

Yields true if the given leafid can be found beneath the given node-id.

Air.ptree_maxleafMethod
ptree_maxleaf(nodeid)

Yields the maximum child leaf index assiciated with the given nodeid.

Air.ptree_minleafMethod
ptree_minleaf(nodeid)

Yields the minimum child leaf index associated with the given nodeid.

Air.ptree_minmaxleafMethod
ptree_minmaxleaf(nodeid)

Yields the (min, max) child leaf index assiciated with the given nodeid.

Air.ptree_parentidMethod
ptree_parentid(nodeid0)

Yields the node-id of the parent of the given node. Note that node 0 (the tree's theoretical root) has no parent. If given a node id of 0, this function will return an arbitrary large number.

Air.ptree_shiftMethod
ptree_shift(nodeid)

Yields the shift for the given ptree node id.

Air.pushFunction
push(coll, val)
push(coll1, val1, val2...)

Yields a copy of the given collection coll with the given value val appended. This function is essentially a persistent equivalent of the push! function that never modifies the object coll. For persistent collections in the Air library, this operation is efficient, but for most mutable objects, it is O(n).

See also: Base.push!, pop, Base.setindex!.

Examples

DocTestSetup = quote
    using Air
end
julia> push((:a,:b,:c,:d), :e)
(:a, :b, :c, :d, :e)
julia> u = [:a,:b,:c,:d]; push(u, :e)
5-element Array{Symbol,1}:
 :a
 :b
 :c
 :d
 :e
julia> s = Set([:a, :b, :c]); push(s, :d)
Set{Symbol} with 4 elements:
  :a
  :b
  :d
  :c
julia> d = Dict(:a => 1, :b => 2); push(d, :c => 3, :d => 4)
Dict{Symbol,Int64} with 4 entries:
  :a => 1
  :b => 2
  :d => 4
  :c => 3
Air.pushfirstFunction
pushfirst(coll, val)
pushfirst(coll1, val1, val2...)

Yields a copy of the given collection coll with the given value val prepended. This function is essentially a persistent equivalent of the pushfirst! function that never modifies the object coll. For persistent collections in the Air library, this operation is efficient, but for most mutable objects, it is O(n).

See also: Base.pushfirst!, popfirst, Base.setindex!, push.

Examples

DocTestSetup = quote
    using Air
end
julia> pushfirst((:a,:b,:c,:d), :e)
(:e, :a, :b, :c, :d)

julia> u = [:a,:b,:c,:d]; pushfirst(u, :e)
5-element Array{Symbol,1}:
 :e
 :a
 :b
 :c
 :d

julia> length(u)
4
Air.pzerosMethod
pzeros(dims...)
pzeros(T, dims...)

Yields a persistent array (PArray) of zeros exactly as done by the zeros() function.

See also pones, pfill, zeros

Examples

DocTestSetup = quote
    using Air, SparseArrays
end
julia> pzeros(Integer, 3)
3-element PArray{Integer,1}:
 0
 0
 0

julia> pzeros(Bool, (1,2))
1×2 PArray{Bool,2}:
 0  0

julia> pzeros(2, 3)
2×3 PArray{Float64,2}:
 0.0  0.0  0.0
 0.0  0.0  0.0

julia> pzeros((1, 1, 1, 1))
1×1×1×1 PArray{Float64,4}:
[:, :, 1, 1] =
 0.0
Air.resetMethod
reset(actor, x)

If the given actor is in an error state, this (1) resets it, meaning it will start handling sent messages again, (2) gives it the new initial value x, and (3) yields the ActorException object that was just clared. If the actor is not in an error state, this just yields nothing.

Air.sendMethod

send(fn, actor)

The send() method can be used to send a function to an actor. The function fn is put in the actor's queue, which is processed sequentially by a separate thread. In the actual function call that is evaluated in this separate thread, the function is passed the stored value of the actor, and the return value of the function becomes the new stored value of the actor.

Note that the value of an actor when send() is called does not make any guarantee about its value when the function that is sent gets evaluated–-other functions may be processed in the interim.

If send() is called inside of a transaction, then the function is not immediately queued but rather is held until the transaction successfully completes. Once this happens, all sends are dispatched simultaneously such that two sends to the same actor during the same transaction will always run back-to-back in the actor's processing thread.

Important. Due to the design pattern described in the previous paragraph, one should never wait on the result of a function sent to an actor during a transaction. This mistake might be made, for example, by sendng an actor, during a transactoin, a function that delivers some result to a Promise object. If the sending thread then waits on that promise while still in the same transaction then it will deadlock because the sent function is not put in the actor's queue until the enclosing transaction is finished. Thus the promise will never recieve the result from the actor.

TL;DR–-When you touch an actor in a transaction, it's value freezes inside the transaction. So if the transaction somehow waits for the actor to update or to do something, that transaction will deadlock.

Air.setfilter!Method
setfilter!(vol, fn)

Sets the filter-function associated with the Volatile object vol. Any time that the vol is set (vol[] = x) the filter-function is called and the value saved in vol is instead fn(x). This must be called within a transaction.

Air.setfinalize!Method
setfinalize!(vol, fn)

Sets the finalize-function associated with the Volatile object vol. Any time that a transaction contains a change to vol, immediately prior to making an attempt at committing the transaction, the finalize function is called and the value committed to vol is instead fn(x) where x is the value set to vol in the transaction. This funvtion must also be called within a transaction.

Air.setvarsFunction
setvars(f, vardict)

Runs the function f in a context in which all Var objectss have been bound to the values given in the dictionary vardict. The keys of this dictionary must be Var objects. Once the function f has finished running, the Var objects are reverted to their calling-frame values. The current vardict object can be obtained by calling vars().

See also: Var, @var, vars, withvars, wrapwithvars, wrapsetvars

Examples

DocTestSetup = quote
    using Air
end
julia> v = Var{Symbol}(:initval)
Var{Symbol}(@hxC65AWl: :initval; init=:initval)

julia> v[]
:initval

julia> setvars(IdDict(v => :newval)) do; v[] end
:newval
Air.setweightMethod
setweight(h, x, w)

Sets the weight of the value x in the given persistent heap or persistent weighted collection object h to be w and yields the new updated version of h. If x is not already in the object h, then an error is thrown.

See also: getweight, PWDict, PWSet.

Examples

DocTestSetup = quote
    using Air
end
julia> d = PWSet{Symbol}(:a => 1.0, :b => 2.0, :c => 3.0)
PWSet{Symbol,Float64} with 3 elements:
  :c
  :b
  :a

julia> setweight(d, :a, 4.0)
PWSet{Symbol,Float64} with 3 elements:
  :a
  :c
  :b
Air.takeMethod
take(promise)

Yields the value delivered to the given Promise object after suspending the current thread to wait for the value if necessary.

See also Promise, Base.put!.

DocTestSetup = quote
    using Air
end
julia> p = Promise()
Promise{Any}(<...>)

julia> put!(p, :done)
:done

julia> p
Promise{Any}(:done)

julia> take(p)
:done
Air.txMethod
tx(fn)

Runs the given function in a transaction and yields the result. The function fn is called as fn() without arguments.

Air.tx_actordataMethod
tx_actordata(a)

Yields the in-transaction data for the Actor object a. If a is in an error-state, then throws an ActorException. If there is no transaction currently running, yields nothing.

This function is considered part of the internal/private interface of Air and shouldn't generally be called outside of it.

Air.varsFunction
vars()

Yields an IdDict{Var,Any} object that contains a mapping of all Var objects whose current in-task value is not its default value to that Var's currently assigned value. The dictionary returned by vars may be later restored using the function setvars.

See also: setvars, withvars, wrapwithvars, Var.

Examples

DocTestSetup = quote
    using Air
end
julia> vars()
IdDict{Var,Any}()
julia> @var v = :test::Symbol
Var{Symbol}(@h4G6oRR9s: :test; init=:test)

julia> withvars(v => :temp) do; vars() end
IdDict{Var,Any} with 1 entry:
  Var{Symbol}(@AaE16J5Pic8) => :temp
Air.voldata_finalizeMethod
voldata_finalize(voldata)

Calls the finalize function of the given volatile state object (of type VolatileData) if necessary. Yields the new VolatileData object, which may be voldata if there is no finalizer or nothing has changed.

This function is a private/internal implementation detail of the Air library.

Air.withvarsFunction
withvars(f, var1 => val1, var2 => val2...)
withvars(f, vardict)

Runs the function f in a context in which the given Vars have been bound to the given values. In the vase of a dictionary passed as the second argument, the keys must be Var objects. Once the function f has finished running, the Var objects are reverted to their calling-frame values.

See also: Var, @var, vars, setvars, wrapwithvars, wrapsetvars

Examples

DocTestSetup = quote
    using Air
end
julia> v = Var{Symbol}(:initval)
Var{Symbol}(@cFgU9Kqe8: :initval; init=:initval)

julia> v[]
:initval

julia> withvars(v => :newval) do; v[] end
:newval
Air.wrapsetvarsFunction
wrapsetvars(f, vardict)

Equivalent to setvars(f, args...) except that instead of running f immediately in the context of the modified Vars, yields a wrapper around f that, when called, passes all arguments to f, which is run using the given variable bindings in the dictionary vardict.

See also: Var, @var, vars, withvars, setvars, wrapwithvars

Examples

DocTestSetup = quote
    using Air
end
julia> v = Var{Int}(0)
Var{Int64}(@F6ku5d8: 0; init=0)

julia> v[]
0

julia> vs = withvars(v => 2) do; vars() end; length(vs)
1

julia> f = wrapsetvars(vs) do x; x + v[] end; f(10)
12
Air.wrapwithvarsFunction
wrapwithvars(f, var1 => val1, var2 => val2...)
wrapwithvars(f, vardict)

Equivalent to withvars(f, args...) except that instead of running f immediately in the context of the modified Vars, yields a wrapper around f that, when called, passes all arguments to f, which is run using the current variable bindings plus any given bindings. Notable, wrapwithvars(f) will create a wrapped version of f that uses the Var bindings in the current task.

See also: Var, @var, vars, withvars, setvars, wrapsetvars

Examples

DocTestSetup = quote
    using Air
end
julia> v = Var{Int}(0)
Var{Int64}(@JIm7aUS2sOl: 0; init=0)

julia> v[]
0

julia> f = wrapwithvars(v => 2) do x; x + v[] end; f(10)
12
Base.setindexMethod
setindex(coll, val, index)

Yields a copy of the given collection coll with the value val set at the given index. This is a persistent version of setindex! and works for most collection types including Arrays, Dicts, IdDicts, and Air's persistent versions of these.

Note that setindex() always returns a copy of the argument coll or fails. For Air's persistent collections these operations are efficient, but for the mutable counterparts, they are typically O(n).

See also: Base.setindex!, push.

Examples

DocTestSetup = quote
    using Air
end
julia> setindex((:a,:b,:e,:d), :c, 3)
(:a, :b, :c, :d)
julia> u = [:a,:b,:e,:d]; v = setindex(u, :c, 3)
4-element Array{Symbol,1}:
 :a
 :b
 :c
 :d

julia> u == v
false

julia> u[3]
:e
julia> d1 = Dict(); setindex(d1, 10, :a)
Dict{Any,Any} with 1 entry:
  :a => 10

julia> d1
Dict{Any,Any}()
SparseArrays.dropzerosMethod
dropzeros(p::PArray)

Drops explicit values of the given array p that are equal to the array's default value. This differs from the SparseArrays implementation of dropzeros() only in that PArrays allow arbitrary default values, while SparseArrays allow only the default value of zero.

Note that under most circumstances, a PArrray will not encode explicit zeros, so this function typically returns the object p untouched.

See also: SparseArrays.nnz, SparseArrays.findnz, PArray.

Examples

DocTestSetup = quote
    using Air, SparseArrays
end
julia> u = PVector{Int}([0,1,2,3])
4-element PArray{Int64,1}:
 0
 1
 2
 3

julia> dropzeros(u) === u
true

julia> v = setindex(u, 0, 3)
4-element PArray{Int64,1}:
 0
 1
 0
 3

julia> dropzeros(v) === v
true
SparseArrays.findnzMethod
findnz(p::PArray)

Yields the explicitly set elements of the given persistent array p. This method is identical to the typical SparseArrays implementation of findnz() except that it respects the arbitrary default-value that persistent arrays are allowed to have rather than assuming that this value is a zero, as is done in the SparseArrays library.

Note that under most circumstances, a PArray will not encode explicit zeros, so this function typically returns indices and values for all values that aren't equal to the default value of the array p (which is zero by default).

See also: SparseArrays.nnz, PArray.

Examples

DocTestSetup = quote
    using Air, SparseArrays
end
julia> u = PVector([0,10,20,30])
4-element PArray{Int64,1}:
  0
 10
 20
 30

julia> findnz(u)
([1, 2, 3, 4], [0, 10, 20, 30])
julia> u = setindex(PVector(0.0, 4), 20, 2)
4-element PArray{Float64,1}:
  0.0
 20.0
  0.0
  0.0

julia> findnz(u)
([2], [20.0])
SparseArrays.nnzMethod
nnz(p::PArray)

Yields the number of explicitly set values in the persistent array p, regardless of the number that are zero. This is different from the sparse-array library only in that persistent arrays support arbitrary default values instead of supporting only the value zero. Thus this counts explicit values instead of non-zero values.

Examples

DocTestSetup = quote
    using Air, SparseArrays
end
julia> u = PVector{Int}(0, (4,))
4-element PArray{Int64,1}:
 0
 0
 0
 0

julia> v = setindex(u, 2, 3)
4-element PArray{Int64,1}:
 0
 0
 2
 0

julia> nnz(v)
1

julia> nnz(u)
0
SparseArrays.nonzerosMethod
nonzeros(p::PArray)

Yields the explicitly set values of the given persistent array p. This method is identical to the typical SparseArrays implementation of nonzeros() for its sparse array classes except that it returns a persistent array of values and that it respects the arbitrary default-value that persistent arrays are allowed to have rather than assuming that this value is a zero, as is done in the SparseArrays library.

Note that because PArrays don't typically store values equal to their default value explicitly, this will typically yield a vector of every non-default value in the array.

See also: SparseArrays.findnz, SparseArrays.nnz, PArray.

Examples

DocTestSetup = quote
    using Air, SparseArrays
end
julia> u = PVector([0,10,20,30])
4-element PArray{Int64,1}:
  0
 10
 20
 30

julia> nonzeros(u)
4-element PArray{Int64,1}:
  0
 10
 20
 30
julia> u = setindex(PVector(0.0, 4), 20, 2)
4-element PArray{Float64,1}:
  0.0
 20.0
  0.0
  0.0

julia> nonzeros(u)
1-element PArray{Float64,1}:
 20.0
Air.@delayMacro
@delay expression

Yields a Delay object that matches the given expression. The expression may be one of the following:

  1. A function of no arguments, such as () -> 10; in this case the delay is made from this function (i.e., the RHS is the -> expression that is delayed).
  2. A function with a set of symbol arguments evaluates the RHS but uses a let statement to wrap all the symbols in the LHS into a closure.
  3. An expression, which is treated as equivalent to () -> expression.

Optionally, the expression or LHS may be tagged with a type T. In this case, a Delay{T} object is yielded instead of a Delay{Any}.

See also: Delay, LazyDict

Examples

DocTestSetup = quote
    using Air
end
julia> # Create a Delay with a long run time.
       d = (@delay (println("Running."); sleep(2); 10)::Int64)
Delay{Int64}(<...>)

julia> # Start a few threads, each of which attempt to read it. The function will
       # only run once.
       for th in [(Threads.@spawn d[]) for _ in 1:5]; wait(th) end
Running.

julia> # Ensure that it produced the correct value and doesn't run again.
       d[]
10

julia> # The display now shows the realized value also.
       d
Delay{Int64}(10)

julia> # Create a Delay with a locally-bound symbol.
       d2 = (@delay (d) -> (d[] / 20.0)::Float64)
Delay{Float64}(<...>)

julia> # We can rebind d without affecting d2.
       d = 10
10

julia> d2[]
0.5
Air.@memoizeMacro
@memoize name(args...) = expr
@memoize name(args...) where {...} = expr

@memoize is a macro for declaring that the function declaration that follows should be memoized in a private dictionary and any pre-calculated value should be returned from that dictionary instead of being recalculated. All memoization is thread-safe: expr is only ever evaluated by one thread at a time, and is only ever evaluated once per unique set of arguments.

Note that arguments are memoized according to equality, so the use of mutable arguments can result in undefined behavior of those arguments are later changed.

Examples

DocTestSetup = quote
    using Air
end
julia> @memoize fib(n::Int) = begin
           println("Calculating fib($n)...")
           if n < 1
               return 0
           elseif n == 1
               return 1
           else
               return fib(n-1) + fib(n - 2)
           end
       end::Int
fib (generic function with 1 method)

julia> fib(5)
Calculating fib(5)...
Calculating fib(4)...
Calculating fib(3)...
Calculating fib(2)...
Calculating fib(1)...
Calculating fib(0)...
5

julia> fib(6)
Calculating fib(6)...
8
Air.@pMacro
@p{k1 => v1, k2 => v2, ...}
@p[x1, x2, ...]
@p[x1 x2...]
@p(x1, x2, ...)

Yields a persistent data structure, depending on how the macro is called. This is a shorthand for calling the various constructors directly. The following expressions are equivalent:

  • @p{k1 => v1, k2 => v2, ...} and PDict(k1 => v1, k2 => v2, ...)
  • @p[x1, x2, ...] and PVector([x1, x2, ...])
  • @p[x1 x2 ...] and PArray([x1 x2 ...])
  • @p(x1, x2, ...) and PSet([x1, x2, ...]

See also: PDict, PVector, PArray, PSet.

Examples

DocTestSetup = quote
    using Air
end
julia> @p{:a => 1, :b => 2, :c => 3}
PDict{Symbol,Int64} with 3 entries:
  :c => 3
  :a => 1
  :b => 2
julia> @p[1, 2, 3, 4]
4-element PArray{Int64,1}:
 1
 2
 3
 4
julia> @p[:q2 :q1; :q3 :q4]
2×2 PArray{Symbol,2}:
 :q2  :q1
 :q3  :q4
julia> @p(:a, :b, :a, :c)
PSet{Symbol} with 3 elements:
  :c
  :a
  :b
Air.@txMacro
@tx expr

The macro @tx should be followed by an expression; that expression is run in an atomic transaction.

Air.@varMacro
@var

Convenient syntax for creating a task-local Var object: @var name = initval will construct a Var object with the given initial value. @var name = initval::T will create a Var{T} object.

See also: Var.

Examples

DocTestSetup = quote
    using Air
end
julia> @var v = :start_sym
Var{Symbol}(@JIm7aUS2sOl: :start_sym; init=:start_sym)

julia> @var u = :start_sym::Any
Var{Any}(@JIm7aUS2sOl: :start_sym; init=:start_sym)