-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Priority as number #90
Changes from all commits
6d46c77
59d237d
f0303d9
d8e1320
ba6f5ea
2efeae2
7913399
485d520
a4df1e6
c19c4f6
fae28d5
deb26f2
b60be22
4f98ac3
61f0693
e02cda2
c3ba26d
1123ccc
d9e16cc
aa10136
a292a9c
baa80b4
b21674b
3b46b15
cac0fc1
32fccd3
cedae0b
54238ec
136aecf
944135a
fbbc732
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
Base.@deprecate put(args...) put!(args...) | ||
Base.@deprecate put(args...; kwargs...) put!(args...; kwargs...) | ||
#Base.@deprecate request(args...; kwargs...) lock(args...; kwargs...) # Not the same: `request` needs to be yielded, while `lock` yields itself | ||
#Base.@deprecate tryrequest(args...; kwargs...) trylock(args...; kwargs...) # Not the same: `request` needs to be yielded, while `lock` yields itself | ||
Base.@deprecate release(args...; kwargs...) unlock(args...; kwargs...) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,63 +1,66 @@ | ||
struct StorePutKey{T} <: ResourceKey | ||
priority :: Int | ||
struct StorePutKey{N, T<:Number} <: ResourceKey | ||
id :: UInt | ||
item :: T | ||
StorePutKey{T}(priority, id, item) where T = new(priority, id, item) | ||
item :: N | ||
priority :: T | ||
end | ||
|
||
struct StoreGetKey <: ResourceKey | ||
priority :: Int | ||
struct StoreGetKey{T<:Number} <: ResourceKey | ||
id :: UInt | ||
filter :: Function | ||
priority :: T | ||
end | ||
|
||
""" | ||
Store{T}(env::Environment; capacity::UInt=typemax(UInt)) | ||
Store{N, T<:Number}(env::Environment; capacity::UInt=typemax(UInt)) | ||
|
||
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). | ||
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). | ||
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. | ||
|
||
See [`Container`](@ref) for a more lock-like resource. | ||
|
||
Think of `Resource` and `Container` as locks and of `Store` as channels. They block only if empty (on taking) or full (on storing). | ||
""" | ||
mutable struct Store{T} <: AbstractResource | ||
mutable struct Store{N, T<:Number} <: AbstractResource | ||
env :: Environment | ||
capacity :: UInt | ||
load :: UInt | ||
items :: Dict{T, UInt} | ||
items :: Dict{N, UInt} | ||
seid :: UInt | ||
put_queue :: DataStructures.PriorityQueue{Put, StorePutKey{T}} | ||
get_queue :: DataStructures.PriorityQueue{Get, StoreGetKey} | ||
function Store{T}(env::Environment; capacity=typemax(UInt)) where {T} | ||
new(env, UInt(capacity), zero(UInt), Dict{T, UInt}(), zero(UInt), DataStructures.PriorityQueue{Put, StorePutKey{T}}(), DataStructures.PriorityQueue{Get, StoreGetKey}()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The explicit There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SimJulia.jl had the |
||
put_queue :: DataStructures.PriorityQueue{Put, StorePutKey{N, T}} | ||
get_queue :: DataStructures.PriorityQueue{Get, StoreGetKey{T}} | ||
function Store{N, T}(env::Environment; capacity=typemax(UInt)) where {N, T<:Number} | ||
new(env, UInt(capacity), zero(UInt), Dict{N, UInt}(), zero(UInt), DataStructures.PriorityQueue{Put, StorePutKey{N, T}}(), DataStructures.PriorityQueue{Get, StoreGetKey{T}}()) | ||
end | ||
end | ||
|
||
function Store{N}(env::Environment; capacity=typemax(UInt)) where {N} | ||
Store{N, Int}(env; capacity=UInt(capacity)) | ||
end | ||
|
||
""" | ||
put!(sto::Store, item::T) | ||
|
||
Put an item into the store. Returns the put event, blocking if the store is full. | ||
""" | ||
function put!(sto::Store{T}, item::T; priority::Int=0) where T | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This does not need to be modified, but just FYI, the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They are still useful as a type assert though There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we now convert to the appropriate type given the type of the Store |
||
function put!(sto::Store{N, T}, item::N; priority=zero(T)) where {N, T<:Number} | ||
put_ev = Put(sto.env) | ||
sto.put_queue[put_ev] = StorePutKey{T}(priority, sto.seid+=one(UInt), item) | ||
sto.put_queue[put_ev] = StorePutKey{N, T}(sto.seid+=one(UInt), item, T(priority)) | ||
@callback trigger_get(put_ev, sto) | ||
trigger_put(put_ev, sto) | ||
put_ev | ||
end | ||
|
||
get_any_item(::T) where T = true | ||
get_any_item(::N) where N = true | ||
|
||
function get(sto::Store{T}, filter::Function=get_any_item; priority::Int=0) where T | ||
function get(sto::Store{N, T}, filter::Function=get_any_item; priority=zero(T)) where {N, T<:Number} | ||
get_ev = Get(sto.env) | ||
sto.get_queue[get_ev] = StoreGetKey(priority, sto.seid+=one(UInt), filter) | ||
sto.get_queue[get_ev] = StoreGetKey(sto.seid+=one(UInt), filter, T(priority)) | ||
@callback trigger_put(get_ev, sto) | ||
trigger_get(get_ev, sto) | ||
get_ev | ||
end | ||
|
||
function do_put(sto::Store{T}, put_ev::Put, key::StorePutKey{T}) where {T} | ||
function do_put(sto::Store{N, T}, put_ev::Put, key::StorePutKey{N, T}) where {N, T<:Number} | ||
if sto.load < sto.capacity | ||
sto.load += one(UInt) | ||
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} | |
false | ||
end | ||
|
||
function do_get(sto::Store{T}, get_ev::Get, key::StoreGetKey) where {T} | ||
function do_get(sto::Store{N, T}, get_ev::Get, key::StoreGetKey{T}) where {N, T<:Number} | ||
for (item, number) in sto.items | ||
if key.filter(item) | ||
sto.load -= one(UInt) | ||
|
@@ -126,4 +129,4 @@ tryrequest(::Store) = error("There is no well defined way to \"request\" a Store | |
|
||
An alias for `get(::Store)` for easier interoperability with the `Base.Channel` interface. Blocks if the store is empty. | ||
""" | ||
take!(sto::Store, filter::Function=get_any_item; priority::Int=0) = get(sto, filter; priority) | ||
take!(sto::Store, filter::Function=get_any_item; priority=0) = get(sto, filter; priority) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
using ConcurrentSim | ||
|
||
## Containers with Float64 priority | ||
sim = Simulation() | ||
con = Container{Float64}(sim,0) | ||
put!(con, 1; priority = 10) | ||
put!(con, 1; priority = 9.1) | ||
put!(con, 1; priority = UInt(9)) | ||
put!(con, 1; priority = BigInt(8)) | ||
put!(con, 1; priority = BigFloat(7.1)) | ||
put!(con, 1; priority = 7) | ||
put!(con, 1; priority = 6.1) | ||
put!(con, 1; priority = BigInt(5)) | ||
put!(con, 1; priority = BigFloat(-Inf)) | ||
@show keys(con.put_queue) | ||
|
||
## Containers with Int64 priority | ||
sim = Simulation() | ||
con = Container{Int}(sim,0) | ||
put!(con, 1; priority = 10) | ||
put!(con, 1; priority = 9.0) | ||
put!(con, 1; priority = UInt(9)) | ||
put!(con, 1; priority = BigInt(8)) | ||
put!(con, 1; priority = BigFloat(7.0)) | ||
put!(con, 1; priority = 7) | ||
put!(con, 1; priority = 6.0) | ||
put!(con, 1; priority = BigInt(5)) | ||
put!(con, 1; priority = typemin(Int)) | ||
@show keys(con.put_queue) | ||
|
||
## Stores with Float64 priority | ||
sim = Simulation() | ||
sto = Store{Symbol,Float64}(sim; capacity = UInt(5)) | ||
put!(sto, :a; priority = 10) | ||
put!(sto, :a; priority = 9.1) | ||
put!(sto, :a; priority = UInt(9)) | ||
put!(sto, :a; priority = BigInt(8)) | ||
put!(sto, :a; priority = BigFloat(7.1)) | ||
put!(sto, :b; priority = 7) | ||
put!(sto, :b; priority = 6.1) | ||
put!(sto, :b; priority = BigInt(5)) | ||
put!(sto, :b; priority = BigFloat(-Inf)) | ||
@show sto.items | ||
@show keys(sto.put_queue) | ||
|
||
## Stores with Int64 priority | ||
sim = Simulation() | ||
sto = Store{Symbol,Int}(sim; capacity = UInt(5)) | ||
put!(sto, :a; priority = 10) | ||
put!(sto, :a; priority = 9.0) | ||
put!(sto, :a; priority = UInt(9)) | ||
put!(sto, :a; priority = BigInt(8)) | ||
put!(sto, :a; priority = BigFloat(7.0)) | ||
put!(sto, :b; priority = 7) | ||
put!(sto, :b; priority = 6.0) | ||
put!(sto, :b; priority = BigInt(5)) | ||
put!(sto, :b; priority = typemin(UInt)) | ||
@show sto.items | ||
@show keys(sto.put_queue) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems a lot of these type restriction can simply be dropped. Types in function signatures are used only for dispatch, they do not provide performance improvements. And it seems types in kwargs do not even participate in dispatch (see https://discourse.julialang.org/t/force-specialization-on-kwargs/34789/14 ). So this makes types for kwargs (and in particular abstract types) not particularly valuable. In most of these situations (function signatures) you can just delete the
::Int
, no need to add::Number
.