StaticStorages.jl provides a general mechanism for providing static storages allocated at code-definition (macro expansion) time. These storages are discoverable across packages. It is useful for inserting performance counters and event trackers in distinct packages.
Arbitrary objects can be stored via put!
and retrieved via get
:
julia> using StaticStorages
julia> key = StaticStorages.put!(@__MODULE__, [123]);
julia> StaticStorages.get(key) == [123]
true
julia> push!(StaticStorages.get(key), 456);
julia> StaticStorages.get(key) == [123, 456]
true
A unique bucket can be allocated with StaticStorages.BucketKey()
.
julia> using StaticStorages
julia> bucketkey = StaticStorages.BucketKey();
julia> key = StaticStorages.put!(@__MODULE__, bucketkey, []);
julia> StaticStorages.get(bucketkey, key) == []
true
julia> StaticStorages.getbucket(bucketkey)[key] == []
true
module CounterDemo
using StaticStorages
const COUNTER_BUCKET = StaticStorages.BucketKey()
macro count()
counter = Threads.Atomic{UInt}(0) # allocate a "static storage" at macro expansion time
key = StaticStorages.put!(__module__, COUNTER_BUCKET, counter)
quote
$(QuoteNode(counter))[] += 1
$(QuoteNode(key))
end
end
counters() = StaticStorages.getbucket(COUNTER_BUCKET)
end # module CounterDemo
count_user_a() = CounterDemo.@count
count_user_b() = CounterDemo.@count
ka = count_user_a()
kb = count_user_b()
count_user_b()
count_user_a()
count_user_a()
println("count_user_a() called ", CounterDemo.counters()[ka][], " times")
println("count_user_b() called ", CounterDemo.counters()[kb][], " times")
# output
count_user_a() called 3 times
count_user_b() called 2 times
In a more practical example, the object put via StaticStorages.put!
can also
contain meta information such as the file and the line number (__source__
). A
global summary can then be generated by iterating over the entry in the
dictionary returned from StaticStorages.getbucket
.
Note that even though __module__
is passed to StaticStorages.put!
, the
bucket returned from StaticStorages.getbucket
contains all values added by
StaticStorages.put!
in all modules and packages.
StaticStorages.jl stores the values in a global dictionary. The import hook is
used for merging the values generated during precompilation. However, it does
not interfere with user-defined __init__
function.