Skip to content

Commit f1b4e6c

Browse files
committed
Code review
1 parent afd28be commit f1b4e6c

9 files changed

Lines changed: 99 additions & 101 deletions

File tree

src/SimJulia.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,24 @@ module SimJulia
1212

1313
export AbstractEvent
1414
export value, state, environment
15-
export Simulation
16-
export run, now, active_process
1715
export Event, Timeout
18-
export succeed, fail, append_callback, @callback, remove_callback
16+
export succeed, fail, @callback, remove_callback
1917
export Operator
2018
export (&), (|)
19+
export Simulation
20+
export run, now, active_process
2121
export Process, @process
2222
export yield, interrupt
23-
export FiniteStateMachine, @stateful, @yield, iscoroutinedone
23+
export FiniteStateMachine, @stateful, @yield
2424
export Coroutine, @coroutine
2525
export Container, Resource, Store
2626
export Put, Get, Request, Release, cancel, capacity, request, @request
2727

2828
include("base.jl")
29-
include("simulations.jl")
3029
include("events.jl")
3130
include("operators.jl")
3231
include("tasks/base.jl")
32+
include("simulations.jl")
3333
include("processes.jl")
3434
include("finitestatemachines/utils.jl")
3535
include("finitestatemachines/transforms.jl")

src/base.jl

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,37 @@ end
5656
function remove_callback(cb::Function, ev::AbstractEvent)
5757
DataStructures.dequeue!(ev.bev.callbacks, cb)
5858
end
59+
60+
function schedule(ev::AbstractEvent, delay::Number=zero(Float64); priority::Int8=zero(Int8), value::Any=nothing)
61+
env = environment(ev)
62+
bev = ev.bev
63+
bev.value = value
64+
env.heap[bev] = EventKey(env.time + delay, priority, env.sid+=one(UInt))
65+
bev.state = scheduled
66+
end
67+
68+
struct StopSimulation <: Exception
69+
value :: Any
70+
function StopSimulation(value::Any=nothing)
71+
new(value)
72+
end
73+
end
74+
75+
function stop_simulation(ev::AbstractEvent)
76+
throw(StopSimulation(value(ev)))
77+
end
78+
79+
function run(env::Environment, until::AbstractEvent)
80+
@callback stop_simulation(until)
81+
try
82+
while true
83+
step(env)
84+
end
85+
catch exc
86+
if isa(exc, StopSimulation)
87+
return exc.value
88+
else
89+
rethrow(exc)
90+
end
91+
end
92+
end

src/coroutines.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ function execute(ev::AbstractEvent, proc::Coroutine)
2727
target = proc.fsm(value(ev))
2828
reset_active_process(env)
2929
if iscoroutinedone(proc.fsm)
30-
schedule(proc.bev, value=target)
30+
schedule(proc; value=target)
3131
else
32-
proc.target = state(target) == triggered ? Timeout(env, value=value(target)) : target
33-
proc.resume = append_callback(execute, proc.target, proc)
32+
proc.target = state(target) == triggered ? Timeout(env; value=value(target)) : target
33+
proc.resume = @callback execute(proc.target, proc)
3434
end
3535
catch exc
3636
rethrow(exc)
@@ -40,7 +40,7 @@ end
4040
function interrupt(proc::Coroutine, cause::Any=nothing)
4141
if !iscoroutinedone(proc.fsm)
4242
remove_callback(proc.resume, proc.target)
43-
proc.target = Timeout(environment(proc), priority=typemax(Int8), value=InterruptException(proc, cause))
44-
proc.resume = append_callback(execute, proc.target, proc)
43+
proc.target = Timeout(environment(proc); priority=typemax(Int8), value=InterruptException(proc, cause))
44+
proc.resume = @callback execute(proc.target, proc)
4545
end
4646
end

src/events.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,23 @@ end
88
function succeed(ev::Event; priority::Int8=zero(Int8), value::Any=nothing) :: Event
99
sta = state(ev)
1010
(sta == scheduled || sta == triggered) && throw(EventNotIdle(ev))
11-
schedule(ev.bev, priority=priority, value=value)
11+
schedule(ev; priority=priority, value=value)
1212
ev
1313
end
1414

1515
function fail(ev::Event, exc::Exception; priority::Int8=zero(Int8)) :: Event
16-
succeed(ev, priority=priority, value=exc)
16+
succeed(ev; priority=priority, value=exc)
1717
end
1818

1919
struct Timeout <: AbstractEvent
2020
bev :: BaseEvent
2121
function Timeout(env::Environment, delay::Number=0; priority::Int8=zero(Int8), value::Any=nothing)
2222
ev = new(BaseEvent(env))
23-
schedule(ev.bev, delay, priority=priority, value=value)
23+
schedule(ev, delay; priority=priority, value=value)
2424
ev
2525
end
2626
end
2727

28-
function run(sim::Simulation, until::Number=typemax(Float64))
29-
run(sim, Timeout(sim, until-now(sim)))
28+
function run(env::Environment, until::Number=typemax(Float64))
29+
run(env, Timeout(env, until-now(env)))
3030
end

src/operators.jl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct Operator <: AbstractEvent
1515
event_state_values = Dict{AbstractEvent, StateValue}()
1616
for ev in tuple(fev, events...)
1717
event_state_values[ev] = StateValue(state(ev))
18-
append_callback(check, ev, op, event_state_values)
18+
@callback check(ev, op, event_state_values)
1919
end
2020
op
2121
end
@@ -25,34 +25,34 @@ function check(ev::AbstractEvent, op::Operator, event_state_values::Dict{Abstrac
2525
val = value(ev)
2626
if state(op) == idle
2727
if isa(val, Exception)
28-
schedule(op.bev, value=val)
28+
schedule(op; value=val)
2929
else
3030
event_state_values[ev] = StateValue(state(ev), val)
3131
if op.eval(collect(values(event_state_values)))
32-
schedule(op.bev, value=event_state_values)
32+
schedule(op; value=event_state_values)
3333
end
3434
end
3535
elseif state(op) == scheduled
3636
if isa(val, Exception)
37-
schedule(op.bev, priority=typemax(Int8), value=val)
37+
schedule(op; priority=typemax(Int8), value=val)
3838
else
3939
event_state_values[ev] = StateValue(state(ev), val)
4040
end
4141
end
4242
end
4343

4444
function eval_and(state_values::Vector{StateValue})
45-
return all(map((sv)->sv.state == triggered, state_values))
45+
all(map((sv)->sv.state == triggered, state_values))
4646
end
4747

4848
function eval_or(state_values::Vector{StateValue})
49-
return any(map((sv)->sv.state == triggered, state_values))
49+
any(map((sv)->sv.state == triggered, state_values))
5050
end
5151

5252
function (&)(ev1::AbstractEvent, ev2::AbstractEvent)
53-
return Operator(eval_and, ev1, ev2)
53+
Operator(eval_and, ev1, ev2)
5454
end
5555

5656
function (|)(ev1::AbstractEvent, ev2::AbstractEvent)
57-
return Operator(eval_or, ev1, ev2)
57+
Operator(eval_or, ev1, ev2)
5858
end

src/processes.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ end
2323
function yield(target::AbstractEvent)
2424
env = environment(target)
2525
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)
26+
proc.target = state(target) == triggered ? Timeout(env; value=value(target)) : target
27+
proc.resume = @callback execute(proc.target, proc)
2828
ret = SimJulia.produce(nothing)
2929
isa(ret, Exception) && throw(ret)
3030
return ret
@@ -36,7 +36,7 @@ function execute(ev::AbstractEvent, proc::Process)
3636
set_active_process(env, proc)
3737
ret = SimJulia.consume(proc.task, value(ev))
3838
reset_active_process(env)
39-
istaskdone(proc.task) && schedule(proc.bev, value=ret)
39+
istaskdone(proc.task) && schedule(proc; value=ret)
4040
catch exc
4141
rethrow(exc)
4242
end
@@ -45,7 +45,7 @@ end
4545
function interrupt(proc::Process, cause::Any=nothing)
4646
if !istaskdone(proc.task)
4747
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)
48+
proc.target = Timeout(environment(proc); priority=typemax(Int8), value=InterruptException(proc, cause))
49+
proc.resume = @callback execute(proc.target, proc)
5050
end
5151
end

src/resources/containers.jl

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,14 @@ end
2929
function Put{N<:Number}(con::Container{N}, amount::N; priority::Int=0) :: Put
3030
put_ev = Put(con.env)
3131
con.Put_queue[put_ev] = ContainerKey(priority, con.seid+=one(UInt), amount)
32-
append_callback(trigger_get, put_ev, con)
32+
@callback trigger_get(put_ev, con)
3333
trigger_put(put_ev, con)
34-
return put_ev
34+
put_ev
3535
end
3636

3737
const Request = Put
3838

39-
Request(res::Resource; priority::Int=0) = Put(res, 1, priority=priority)
39+
Request(res::Resource; priority::Int=0) = Put(res, 1; priority=priority)
4040

4141
macro request(res, req, expr)
4242
esc(quote
@@ -51,12 +51,12 @@ macro request(res, req, expr)
5151
end
5252

5353
function request(func::Function, res::Resource; priority::Int=0)
54-
req = Request(res, priority=priority)
54+
req = Request(res; priority=priority)
5555
try
5656
func(req)
5757
finally
5858
if state(req) == triggered
59-
yield(Release(res, priority=priority))
59+
yield(Release(res; priority=priority))
6060
else
6161
cancel(res, req)
6262
end
@@ -66,29 +66,25 @@ end
6666
function Get{N<:Number}(con::Container{N}, amount::N; priority::Int=0) :: Get
6767
get_ev = Get(con.env)
6868
con.Get_queue[get_ev] = ContainerKey(priority, con.seid+=one(UInt), amount)
69-
append_callback(trigger_put, get_ev, con)
69+
@callback trigger_put(get_ev, con)
7070
trigger_get(get_ev, con)
71-
return get_ev
71+
get_ev
7272
end
7373

7474
const Release = Get
7575

76-
Release(res::Resource; priority::Int=0) = Get(res, 1, priority=priority)
76+
Release(res::Resource; priority::Int=0) = Get(res, 1; priority=priority)
7777

7878
function do_put{N<:Number}(con::Container{N}, put_ev::Put, key::ContainerKey{N}) :: Bool
79-
if con.level + key.amount <= con.capacity
80-
schedule(put_ev.bev)
81-
con.level += key.amount
82-
return true
83-
end
84-
return false
79+
con.level + key.amount > con.capacity && return false
80+
schedule(put_ev)
81+
con.level += key.amount
82+
true
8583
end
8684

8785
function do_get{N<:Number}(con::Container{N}, get_ev::Get, key::ContainerKey{N}) :: Bool
88-
if con.level - key.amount >= zero(N)
89-
schedule(get_ev.bev)
90-
con.level -= key.amount
91-
return true
92-
end
93-
return false
86+
con.level - key.amount < zero(N) && return false
87+
schedule(get_ev)
88+
con.level -= key.amount
89+
true
9490
end

src/resources/stores.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ end
2929
function Put{T}(sto::Store{T}, item::T; priority::Int=0) :: Put
3030
put_ev = Put(sto.env)
3131
sto.Put_queue[put_ev] = StorePutKey(priority, sto.seid+=one(UInt), item)
32-
append_callback(trigger_get, put_ev, sto)
32+
@callback trigger_get(put_ev, sto)
3333
trigger_put(put_ev, sto)
3434
return put_ev
3535
end
@@ -41,15 +41,15 @@ end
4141
function Get{T}(sto::Store{T}, filter::Function=get_any_item; priority::Int=0) :: Get
4242
get_ev = Get(sto.env)
4343
sto.Get_queue[get_ev] = StoreGetKey(priority, sto.seid+=one(UInt), filter)
44-
append_callback(trigger_put, get_ev, sto)
44+
@callback trigger_put(get_ev, sto)
4545
trigger_get(get_ev, sto)
4646
return get_ev
4747
end
4848

4949
function do_put{T}(sto::Store{T}, put_ev::Put, key::StorePutKey{T}) :: Bool
5050
if length(sto.items) < sto.capacity
5151
push!(sto.items, key.item)
52-
schedule(put_ev.bev)
52+
schedule(put_ev)
5353
end
5454
return false
5555
end
@@ -58,7 +58,7 @@ function do_get{T}(sto::Store{T}, get_ev::Get, key::StoreGetKey) :: Bool
5858
for item in sto.items
5959
if key.filter(item)
6060
delete!(sto.items, item)
61-
schedule(get_ev.bev, value=item)
61+
schedule(get_ev; value=item)
6262
break
6363
end
6464
end

src/simulations.jl

Lines changed: 17 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
abstract type AbstractProcess <: AbstractEvent end
22

3+
struct InterruptException <: Exception
4+
by :: AbstractProcess
5+
cause :: Any
6+
end
7+
8+
struct EmptySchedule <: Exception end
9+
310
struct EventKey
411
time :: Float64
512
priority :: Int8
@@ -21,35 +28,6 @@ mutable struct Simulation <: Environment
2128
end
2229
end
2330

24-
function now(sim::Simulation)
25-
sim.time
26-
end
27-
28-
function active_process(sim::Simulation) :: AbstractProcess
29-
get(sim.active_proc)
30-
end
31-
32-
function reset_active_process(sim::Simulation)
33-
sim.active_proc = Nullable{AbstractProcess}()
34-
end
35-
36-
function set_active_process(sim::Simulation, proc::AbstractProcess)
37-
sim.active_proc = Nullable(proc)
38-
end
39-
40-
struct StopSimulation <: Exception
41-
value :: Any
42-
function StopSimulation(value::Any=nothing)
43-
new(value)
44-
end
45-
end
46-
47-
function stop_simulation(ev::AbstractEvent)
48-
throw(StopSimulation(value(ev)))
49-
end
50-
51-
struct EmptySchedule <: Exception end
52-
5331
function step(sim::Simulation)
5432
isempty(sim.heap) && throw(EmptySchedule())
5533
(bev, key) = DataStructures.peek(sim.heap)
@@ -61,28 +39,18 @@ function step(sim::Simulation)
6139
end
6240
end
6341

64-
function run(sim::Simulation, until::AbstractEvent)
65-
append_callback(stop_simulation, until)
66-
try
67-
while true
68-
step(sim)
69-
end
70-
catch exc
71-
if isa(exc, StopSimulation)
72-
return exc.value
73-
else
74-
rethrow(exc)
75-
end
76-
end
42+
function now(sim::Simulation)
43+
sim.time
7744
end
7845

79-
function schedule(bev::BaseEvent, delay::Number=zero(Float64); priority::Int8=zero(Int8), value::Any=nothing)
80-
bev.value = value
81-
bev.env.heap[bev] = EventKey(bev.env.time + delay, priority, bev.env.sid+=one(UInt))
82-
bev.state = scheduled
46+
function active_process(sim::Simulation) :: AbstractProcess
47+
get(sim.active_proc)
8348
end
8449

85-
struct InterruptException <: Exception
86-
by :: AbstractProcess
87-
cause :: Any
50+
function reset_active_process(sim::Simulation)
51+
sim.active_proc = Nullable{AbstractProcess}()
52+
end
53+
54+
function set_active_process(sim::Simulation, proc::AbstractProcess)
55+
sim.active_proc = Nullable(proc)
8856
end

0 commit comments

Comments
 (0)