|
| 1 | +type Process <: AbstractProcess |
| 2 | + bev :: BaseEvent |
| 3 | + task :: Task |
| 4 | + target :: AbstractEvent |
| 5 | + resume :: Function |
| 6 | + function Process(func::Function, env::Environment, args::Any...) |
| 7 | + proc = new() |
| 8 | + proc.bev = BaseEvent(env) |
| 9 | + proc.task = @task func(env, args...) |
| 10 | + proc.target = Timeout(env) |
| 11 | + proc.resume = @callback execute(proc.target, proc) |
| 12 | + return proc |
| 13 | + end |
| 14 | +end |
| 15 | + |
| 16 | +macro process(expr) |
| 17 | + expr.head != :call && error("Expression is not a function call!") |
| 18 | + func = esc(expr.args[1]) |
| 19 | + args = [esc(expr.args[n]) for n in 2:length(expr.args)] |
| 20 | + :(Process($(func), $(args...))) |
| 21 | +end |
| 22 | + |
| 23 | +function yield(target::AbstractEvent) |
| 24 | + env = environment(target) |
| 25 | + proc = active_process(env) |
| 26 | + proc.target = state(target) == triggered ? Timeout(env, value=value(target)) : target |
| 27 | + proc.resume = append_callback(execute, proc.target, proc) |
| 28 | + ret = SimJulia.produce(nothing) |
| 29 | + isa(ret, Exception) && throw(ret) |
| 30 | + return ret |
| 31 | +end |
| 32 | + |
| 33 | +function execute(ev::AbstractEvent, proc::Process) |
| 34 | + try |
| 35 | + env = environment(ev) |
| 36 | + set_active_process(env, proc) |
| 37 | + ret = SimJulia.consume(proc.task, value(ev)) |
| 38 | + reset_active_process(env) |
| 39 | + istaskdone(proc.task) && schedule(proc.bev, value=ret) |
| 40 | + catch exc |
| 41 | + rethrow(exc) |
| 42 | + end |
| 43 | +end |
| 44 | + |
| 45 | +function interrupt(proc::Process, cause::Any=nothing) |
| 46 | + if !istaskdone(proc.task) |
| 47 | + remove_callback(proc.resume, proc.target) |
| 48 | + proc.target = Timeout(environment(proc), priority=typemax(Int8), value=InterruptException(proc, cause)) |
| 49 | + proc.resume = append_callback(execute, proc.target, proc) |
| 50 | + end |
| 51 | +end |
0 commit comments