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]
trueA 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] == []
truemodule 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 timesIn 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.