Skip to content

Commit bb72add

Browse files
hdavid16Krastanov
andauthored
Priority as number (#90)
--------- Co-authored-by: Stefan Krastanov <[email protected]> Co-authored-by: Stefan Krastanov <[email protected]>
1 parent c62a6e5 commit bb72add

File tree

13 files changed

+125
-58
lines changed

13 files changed

+125
-58
lines changed

docs/src/api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ Private = false
66
```
77

88
```@docs
9-
unlock(res::Container; priority::Int=0)
9+
unlock(res::Resource; priority::Number=0)
1010
take!(sto::Store, filter::Function=get_any_item; priority::Int=0)
1111
```

src/base.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ function remove_callback(cb::Function, ev::AbstractEvent)
6363
i != 0 && deleteat!(ev.bev.callbacks, i)
6464
end
6565

66-
function schedule(ev::AbstractEvent, delay::Number=zero(Float64); priority::Int=0, value::Any=nothing)
66+
function schedule(ev::AbstractEvent, delay::Number=0; priority::Number=0, value::Any=nothing)
6767
state(ev) === processed && throw(EventProcessed(ev))
6868
env = environment(ev)
6969
bev = ev.bev

src/deprecated.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Base.@deprecate put(args...) put!(args...)
1+
Base.@deprecate put(args...; kwargs...) put!(args...; kwargs...)
22
#Base.@deprecate request(args...; kwargs...) lock(args...; kwargs...) # Not the same: `request` needs to be yielded, while `lock` yields itself
33
#Base.@deprecate tryrequest(args...; kwargs...) trylock(args...; kwargs...) # Not the same: `request` needs to be yielded, while `lock` yields itself
44
Base.@deprecate release(args...; kwargs...) unlock(args...; kwargs...)

src/events.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ struct Event <: AbstractEvent
55
end
66
end
77

8-
function succeed(ev::Event; priority::Int=0, value::Any=nothing) :: Event
8+
function succeed(ev::Event; priority::Number=0, value::Any=nothing) :: Event
99
state(ev) !== idle && throw(EventNotIdle(ev))
1010
schedule(ev; priority=priority, value=value)
1111
end
1212

13-
function fail(ev::Event, exc::Exception; priority::Int=0) :: Event
13+
function fail(ev::Event, exc::Exception; priority::Number=0) :: Event
1414
succeed(ev; priority=priority, value=exc)
1515
end
1616

@@ -21,10 +21,10 @@ struct Timeout <: AbstractEvent
2121
end
2222
end
2323

24-
function timeout(env::Environment, delay::Number=0; priority::Int=0, value::Any=nothing)
24+
function timeout(env::Environment, delay::Number=0; priority::Number=0, value::Any=nothing)
2525
schedule(Timeout(env), delay; priority=priority, value=value)
2626
end
2727

28-
function run(env::Environment, until::Number=typemax(Float64))
28+
function run(env::Environment, until::Number=Inf)
2929
run(env, timeout(env, until-now(env)))
3030
end

src/operators.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function check(ev::AbstractEvent, op::Operator, event_state_values::Dict{Abstrac
3232
end
3333
elseif state(op) === scheduled
3434
if isa(val, Exception)
35-
schedule(op; priority=typemax(Int), value=val)
35+
schedule(op; priority=Inf, value=val)
3636
else
3737
event_state_values[ev] = StateValue(state(ev), val)
3838
end

src/processes.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ end
5757
function interrupt(proc::Process, cause::Any=nothing)
5858
env = environment(proc)
5959
if proc.fsmi._state !== 0xff
60-
proc.target isa Initialize && schedule(proc.target; priority=typemax(Int))
61-
target = schedule(Interrupt(env); priority=typemax(Int), value=InterruptException(active_process(env), cause))
60+
proc.target isa Initialize && schedule(proc.target; priority=Inf)
61+
target = schedule(Interrupt(env); priority=Inf, value=InterruptException(active_process(env), cause))
6262
@callback execute_interrupt(target, proc)
6363
end
64-
timeout(env; priority=typemax(Int))
64+
timeout(env; priority=Inf)
6565
end

src/resources/containers.jl

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
struct ContainerKey{N<:Real} <: ResourceKey
2-
priority :: Int
1+
struct ContainerKey{N<:Real, T<:Number} <: ResourceKey
32
id :: UInt
43
amount :: N
4+
priority :: T
55
end
66

77
"""
8-
Container{N}(env::Environment, capacity::N=one(N); level::N=zero(N))
8+
Container{N<:Real, T<:Number}(env::Environment, capacity::N=one(N); level::N=zero(N))
99
1010
A "Container" resource object, storing up to `capacity` units of a resource (of type `N`).
1111
12-
There is a `Resource` alias for `Container{Int}`.
12+
There is a `Resource` alias for `Container{Int, Int}`.
1313
1414
`Resource()` with default capacity of `1` is very similar to a typical lock.
1515
The [`request`](@ref) and [`unlock`](@ref) functions are a convenient way to interact with such a "lock",
@@ -19,27 +19,31 @@ See [`Store`](@ref) for a more channel-like resource.
1919
2020
Think of `Resource` and `Container` as locks and of `Store` as channels. They block only if empty (on taking) or full (on storing).
2121
"""
22-
mutable struct Container{N<:Real} <: AbstractResource
22+
mutable struct Container{N<:Real, T<:Number} <: AbstractResource
2323
env :: Environment
2424
capacity :: N
2525
level :: N
2626
seid :: UInt
27-
put_queue :: DataStructures.PriorityQueue{Put, ContainerKey{N}}
28-
get_queue :: DataStructures.PriorityQueue{Get, ContainerKey{N}}
29-
function Container{N}(env::Environment, capacity::N=one(N); level::N=zero(N)) where {N<:Real}
30-
new(env, capacity, level, zero(UInt), DataStructures.PriorityQueue{Put, ContainerKey{N}}(), DataStructures.PriorityQueue{Get, ContainerKey{N}}())
27+
put_queue :: DataStructures.PriorityQueue{Put, ContainerKey{N, T}}
28+
get_queue :: DataStructures.PriorityQueue{Get, ContainerKey{N, T}}
29+
function Container{N, T}(env::Environment, capacity::N=one(N); level=zero(N)) where {N<:Real, T<:Number}
30+
new(env, capacity, N(level), zero(UInt), DataStructures.PriorityQueue{Put, ContainerKey{N, T}}(), DataStructures.PriorityQueue{Get, ContainerKey{N, T}}())
3131
end
3232
end
3333

34-
function Container(env::Environment, capacity::N=one(N); level::N=zero(N)) where {N<:Real}
35-
Container{N}(env, capacity, level=level)
34+
function Container(env::Environment, capacity::N=one(N); level=zero(N)) where {N<:Real}
35+
Container{N, Int}(env, capacity; level=N(level))
3636
end
3737

38-
const Resource = Container{Int}
38+
function Container{T}(env::Environment, capacity::N=one(N); level=zero(N)) where {N<:Real, T<:Number}
39+
Container{N, T}(env, capacity; level=N(level))
40+
end
41+
42+
const Resource = Container{Int, Int}
3943

40-
function put!(con::Container{N}, amount::N; priority::Int=0) where N<:Real
44+
function put!(con::Container{N, T}, amount::N; priority=zero(T)) where {N<:Real, T<:Number}
4145
put_ev = Put(con.env)
42-
con.put_queue[put_ev] = ContainerKey(priority, con.seid+=one(UInt), amount)
46+
con.put_queue[put_ev] = ContainerKey{N,T}(con.seid+=one(UInt), amount, T(priority))
4347
@callback trigger_get(put_ev, con)
4448
trigger_put(put_ev, con)
4549
put_ev
@@ -52,7 +56,7 @@ Locks the Container (or Resources) and return the lock event.
5256
If the capacity of the Container is greater than 1,
5357
multiple requests can be made before blocking occurs.
5458
"""
55-
request(res::Container; priority::Int=0) = put!(res, 1; priority=priority)
59+
request(res::Resource; priority=0) = put!(res, 1; priority)
5660

5761
"""
5862
tryrequest(res::Container)
@@ -76,14 +80,14 @@ julia> tryrequest(res)
7680
false
7781
```
7882
"""
79-
function tryrequest(res::Container; priority::Int=0)
83+
function tryrequest(res::Container; priority=0)
8084
islocked(res) && return false # TODO check priority
8185
request(res; priority)
8286
end
8387

84-
function get(con::Container{N}, amount::N; priority::Int=0) where N<:Real
88+
function get(con::Container{N, T}, amount::N; priority=zero(T)) where {N<:Real, T<:Number}
8589
get_ev = Get(con.env)
86-
con.get_queue[get_ev] = ContainerKey(priority, con.seid+=one(UInt), amount)
90+
con.get_queue[get_ev] = ContainerKey(con.seid+=one(UInt), amount, T(priority))
8791
@callback trigger_put(get_ev, con)
8892
trigger_get(get_ev, con)
8993
get_ev
@@ -94,16 +98,16 @@ end
9498
9599
Unlocks the Container and return the unlock event.
96100
"""
97-
unlock(res::Container; priority::Int=0) = get(res, 1; priority=priority)
101+
unlock(res::Resource; priority::Number=0) = get(res, 1; priority=priority)
98102

99-
function do_put(con::Container{N}, put_ev::Put, key::ContainerKey{N}) where N<:Real
103+
function do_put(con::Container{N, T}, put_ev::Put, key::ContainerKey{N, T}) where {N<:Real, T<:Number}
100104
con.level + key.amount > con.capacity && return false
101105
schedule(put_ev)
102106
con.level += key.amount
103107
true
104108
end
105109

106-
function do_get(con::Container{N}, get_ev::Get, key::ContainerKey{N}) where N<:Real
110+
function do_get(con::Container{N, T}, get_ev::Get, key::ContainerKey{N, T}) where {N<:Real, T<:Number}
107111
con.level - key.amount < zero(N) && return false
108112
schedule(get_ev)
109113
con.level -= key.amount

src/resources/stores.jl

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,66 @@
1-
struct StorePutKey{T} <: ResourceKey
2-
priority :: Int
1+
struct StorePutKey{N, T<:Number} <: ResourceKey
32
id :: UInt
4-
item :: T
5-
StorePutKey{T}(priority, id, item) where T = new(priority, id, item)
3+
item :: N
4+
priority :: T
65
end
76

8-
struct StoreGetKey <: ResourceKey
9-
priority :: Int
7+
struct StoreGetKey{T<:Number} <: ResourceKey
108
id :: UInt
119
filter :: Function
10+
priority :: T
1211
end
1312

1413
"""
15-
Store{T}(env::Environment; capacity::UInt=typemax(UInt))
14+
Store{N, T<:Number}(env::Environment; capacity::UInt=typemax(UInt))
1615
17-
A store is a resource that can hold a number of items of type `T`. It is similar to a `Base.Channel` with a finite capacity ([`put!`](@ref) blocks after reaching capacity).
16+
A store is a resource that can hold a number of items of type `N`. It is similar to a `Base.Channel` with a finite capacity ([`put!`](@ref) blocks after reaching capacity).
1817
The [`put!`](@ref) and [`take!`](@ref) functions are a convenient way to interact with such a "channel" in a way mostly compatible with other discrete event and concurrency frameworks.
1918
2019
See [`Container`](@ref) for a more lock-like resource.
2120
2221
Think of `Resource` and `Container` as locks and of `Store` as channels. They block only if empty (on taking) or full (on storing).
2322
"""
24-
mutable struct Store{T} <: AbstractResource
23+
mutable struct Store{N, T<:Number} <: AbstractResource
2524
env :: Environment
2625
capacity :: UInt
2726
load :: UInt
28-
items :: Dict{T, UInt}
27+
items :: Dict{N, UInt}
2928
seid :: UInt
30-
put_queue :: DataStructures.PriorityQueue{Put, StorePutKey{T}}
31-
get_queue :: DataStructures.PriorityQueue{Get, StoreGetKey}
32-
function Store{T}(env::Environment; capacity=typemax(UInt)) where {T}
33-
new(env, UInt(capacity), zero(UInt), Dict{T, UInt}(), zero(UInt), DataStructures.PriorityQueue{Put, StorePutKey{T}}(), DataStructures.PriorityQueue{Get, StoreGetKey}())
29+
put_queue :: DataStructures.PriorityQueue{Put, StorePutKey{N, T}}
30+
get_queue :: DataStructures.PriorityQueue{Get, StoreGetKey{T}}
31+
function Store{N, T}(env::Environment; capacity=typemax(UInt)) where {N, T<:Number}
32+
new(env, UInt(capacity), zero(UInt), Dict{N, UInt}(), zero(UInt), DataStructures.PriorityQueue{Put, StorePutKey{N, T}}(), DataStructures.PriorityQueue{Get, StoreGetKey{T}}())
3433
end
3534
end
3635

36+
function Store{N}(env::Environment; capacity=typemax(UInt)) where {N}
37+
Store{N, Int}(env; capacity=UInt(capacity))
38+
end
39+
3740
"""
3841
put!(sto::Store, item::T)
3942
4043
Put an item into the store. Returns the put event, blocking if the store is full.
4144
"""
42-
function put!(sto::Store{T}, item::T; priority::Int=0) where T
45+
function put!(sto::Store{N, T}, item::N; priority=zero(T)) where {N, T<:Number}
4346
put_ev = Put(sto.env)
44-
sto.put_queue[put_ev] = StorePutKey{T}(priority, sto.seid+=one(UInt), item)
47+
sto.put_queue[put_ev] = StorePutKey{N, T}(sto.seid+=one(UInt), item, T(priority))
4548
@callback trigger_get(put_ev, sto)
4649
trigger_put(put_ev, sto)
4750
put_ev
4851
end
4952

50-
get_any_item(::T) where T = true
53+
get_any_item(::N) where N = true
5154

52-
function get(sto::Store{T}, filter::Function=get_any_item; priority::Int=0) where T
55+
function get(sto::Store{N, T}, filter::Function=get_any_item; priority=zero(T)) where {N, T<:Number}
5356
get_ev = Get(sto.env)
54-
sto.get_queue[get_ev] = StoreGetKey(priority, sto.seid+=one(UInt), filter)
57+
sto.get_queue[get_ev] = StoreGetKey(sto.seid+=one(UInt), filter, T(priority))
5558
@callback trigger_put(get_ev, sto)
5659
trigger_get(get_ev, sto)
5760
get_ev
5861
end
5962

60-
function do_put(sto::Store{T}, put_ev::Put, key::StorePutKey{T}) where {T}
63+
function do_put(sto::Store{N, T}, put_ev::Put, key::StorePutKey{N, T}) where {N, T<:Number}
6164
if sto.load < sto.capacity
6265
sto.load += one(UInt)
6366
sto.items[key.item] = get(sto.items, key.item, zero(UInt)) + one(UInt)
@@ -66,7 +69,7 @@ function do_put(sto::Store{T}, put_ev::Put, key::StorePutKey{T}) where {T}
6669
false
6770
end
6871

69-
function do_get(sto::Store{T}, get_ev::Get, key::StoreGetKey) where {T}
72+
function do_get(sto::Store{N, T}, get_ev::Get, key::StoreGetKey{T}) where {N, T<:Number}
7073
for (item, number) in sto.items
7174
if key.filter(item)
7275
sto.load -= one(UInt)
@@ -126,4 +129,4 @@ tryrequest(::Store) = error("There is no well defined way to \"request\" a Store
126129
127130
An alias for `get(::Store)` for easier interoperability with the `Base.Channel` interface. Blocks if the store is empty.
128131
"""
129-
take!(sto::Store, filter::Function=get_any_item; priority::Int=0) = get(sto, filter; priority)
132+
take!(sto::Store, filter::Function=get_any_item; priority=0) = get(sto, filter; priority)

src/simulations.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ end
88

99
struct EmptySchedule <: Exception end
1010

11-
struct EventKey
11+
struct EventKey{N<:Number}
1212
time :: Float64
13-
priority :: Int
13+
priority :: N
1414
id :: UInt
1515
end
1616

src/utils/time.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ function run(env::Environment, until::DateTime)
66
run(env, Dates.datetime2epochms(until))
77
end
88

9-
function timeout(env::Environment, delay::Period; priority::Int=0, value::Any=nothing)
9+
function timeout(env::Environment, delay::Period; priority::Number=0, value::Any=nothing)
1010
time = now(env)
1111
del = Dates.datetime2epochms(Dates.epochms2datetime(time)+delay)-time
1212
timeout(env, del; priority=priority, value=value)

0 commit comments

Comments
 (0)