Processes
Processes are typical event sequences running as asynchronous tasks.
Process Setup
To setup a process, you
- implement it in a function taking a
Clockvariable as its first argument, - wrap it into
Prcand start it as an asynchronous task withprocess!. The@processmacro does this in one call.
DiscreteEvents.Prc — TypePrc(id, f, arg...; kw...)
Prc(f, arg...; kw...)Prepare a function to run as a process and get registered to a clock.
Arguments, Fields
id: some unique identification for registration,f::Function: a functionf(clk, arg...; kw...), must takeclk(aClock) as its first argument,arg...: further arguments tofkw...: keyword arguments tof
Fields identified during registration
id: if it is not provided, some integer will be calculated for it during registration,task::Union{Task,Nothing}: a task structure used for diagnosis,clk::Union{AbstractClock,Nothing}: clock where the process is registered,
The clock clk where a process runs and gets registered is identified during process startup and then passed as 1st argument to f.
DiscreteEvents.process! — Functionprocess!([clk], prc, cycles; <keyword arguments>)Register a Prc to a clock, start an asynchronous task executing the process function in a loop and return the id it was registered with. It can then be found under clk.processes[id].
Arguments
c<:AbstractClock: if not provided, the process runs under𝐶,prc::Prc: it contains a function and its arguments,cycles<:Number=Inf: number of loop cycles the process should run,
Keyword arguments
cid::Int=clk.id: if cid ≠ clk.id, assign the event to the parallel clock with id == cid. This overridesspawn,spawn::Bool=false: if true, the process may be scheduled on another thread in parallel and registered to the thread specific clock.
DiscreteEvents.@process — Macro@process f(arg...) [cycles]Create a process from a function f(arg...).
Wrap a function and its arguments in a Prc and start it with process!.
Arguments
f: a function,arg...: arguments, the first argument must be an AbstractClock,cycles::Int: the number of cycles,fshould run.
Returns
- an
Intprocess id.
Delay and Wait …
Functions implementing processes create events implicitly by calling delay! or wait! on their clock. They wait for resources to be available by using take! and put! on channels. Those calls will suspend an asynchronous task until a given time or until certain conditions are met or requested resources are available.
DiscreteEvents.delay! — Functiondelay!(clk, Δt)
delay!(clk, T, t)Delay (suspend) a process for a time interval Δt on the clock clk.
Arguments
clk::Clock,Δt: time interval,NumberorDistribution,T::Timing: onlyuntilis accepted,t: time delay,NumberorDistribution.
DiscreteEvents.@delay — Macro@delay clk Δt
@delay clk until tDelay a process on a clock clk for a time interval Δt or until a time t.
DiscreteEvents.wait! — Functionwait!(clk, cond)Delay (suspend) a process on a clock clk until a condition has become true.
Arguments
clk::Clock,cond<:Action: a condition, true if all expressions or functions therein return true.
DiscreteEvents.@wait — Macro@wait clk f(arg...)Conditionally wait on a clock clk until f(arg...) returns true.
Interrupts
If other events (e.g. representing reneging customers, failures) interrupt the typical event sequence of a process, it is waiting for a time or condition or resource and not ready to respond to something else. Processes therefore must use exception handling to handle unexpected events.
DiscreteEvents.PrcException — TypePrcException(event, value)An exception to be thrown at processes.
Arguments, fields
event: deliver an event to the interrupted taskvalue: deliver some other value
DiscreteEvents.interrupt! — Functioninterrupt!(p::Prc, ev, value)Interrupt a Prc by throwing a PrcException to it.
An example at DiscreteEventsCompanion illustrates how to handle interrupts to a process. Things can get messy quickly if there are several unusual events which have to be handled in a process.
Now
Processes (or asynchronous tasks in general) transfer IO-operations with a now! call to the (master) clock to ensure they get executed at current clock time. As a convenience you can print directly to the clock.
DiscreteEvents.now! — Functionnow!(clk::Clock, ex::A) where {A<:Action}Transfer an IO-operation ex to clk or if it is a parallel clock to the master clock (on thread 1). The clock executes it before proceeding to the next time step.
Base.print — Methodprint(clk::Clock, [io::IO], x, xs...)Create a now! event to a busy clock clk to print(x, xs...) to io (or to stdout).
If the clock is not busy, x and xs... are printed as usual. print(clk) still prints repr(clk).
Base.println — Methodprintln(clk::Clock, [io::IO], xs...)Create a now! event to a busy clock clk to println(x, xs...) to io (or to stdout).
If the clock is not busy, x and xs... are printed as usual. println(clk) still prints repr(clk).
Examples
The A-B Call Center Problem illustrates how to implement and setup a process. You can find more examples at DiscreteEventsCompanion.