JuliaCollections / LRUCache.jl
Showing 1 of 8 files from the diff.

@@ -7,7 +7,6 @@
Loading
7 7
using Base: Callable
8 8
9 9
_constone(x) = 1
10 -
function _no_callback end
11 10
12 11
# Default cache size
13 12
mutable struct LRU{K,V} <: AbstractDict{K,V}
@@ -16,20 +15,18 @@
Loading
16 15
    currentsize::Int
17 16
    maxsize::Int
18 17
    lock::SpinLock
19 -
    by::Callable
20 -
    eviction_callback::Callable
18 +
    by::Any
19 +
    finalizer::Any
21 20
22 -
    LRU{K, V}(; maxsize::Int, by::Callable = _constone,
23 -
              eviction_callback::Callable = _no_callback) where {K, V} =
24 -
        new{K, V}(Dict{K, V}(), CyclicOrderedSet{K}(), 0, maxsize, SpinLock(),
25 -
                  by, eviction_callback)
21 +
    function LRU{K, V}(; maxsize::Int, by = _constone, finalizer = nothing) where {K, V}
22 +
        dict = Dict{K, V}()
23 +
        keyset = CyclicOrderedSet{K}()
24 +
        new{K, V}(dict, keyset , 0, maxsize, SpinLock(), by, finalizer)
25 +
    end
26 26
end
27 27
28 -
function LRU(; maxsize::Int, by::Callable = _constone,
29 -
             eviction_callback::Callable = _no_callback)
30 -
    return LRU{Any,Any}(maxsize=maxsize, by=by,
31 -
                        eviction_callback=eviction_callback)
32 -
end
28 +
LRU(; maxsize::Int, by = _constone, finalizer = nothing) =
29 +
    LRU{Any,Any}(maxsize = maxsize, by = by, finalizer = finalizer)
33 30
34 31
Base.show(io::IO, lru::LRU{K, V}) where {K, V} =
35 32
    print(io, "LRU{$K, $V}(; maxsize = $(lru.maxsize))")
@@ -93,7 +90,7 @@
Loading
93 90
        _unsafe_resize!(lru, evictions)
94 91
        return v
95 92
    end
96 -
    _notify_evictions!(lru.eviction_callback, evictions)
93 +
    _finalize_evictions!(lru.finalizer, evictions)
97 94
    return v
98 95
end
99 96
function Base.get!(default::Callable, lru::LRU{K, V}, key) where {K, V}
@@ -116,7 +113,7 @@
Loading
116 113
        _unsafe_resize!(lru, evictions)
117 114
    end
118 115
    unlock(lru.lock)
119 -
    _notify_evictions!(lru.eviction_callback, evictions)
116 +
    _finalize_evictions!(lru.finalizer, evictions)
120 117
    return v
121 118
end
122 119
@@ -147,7 +144,7 @@
Loading
147 144
    lock(lru.lock) do
148 145
        if _unsafe_haskey(lru, key)
149 146
            old_v, n, s = lru.dict[key]
150 -
            if lru.eviction_callback !== _no_callback
147 +
            if lru.finalizer !== nothing
151 148
                push!(evictions, (key, old_v))
152 149
            end
153 150
            lru.currentsize -= s
@@ -160,7 +157,7 @@
Loading
160 157
        end
161 158
        _unsafe_resize!(lru, evictions)
162 159
    end
163 -
    _notify_evictions!(lru.eviction_callback, evictions)
160 +
    _finalize_evictions!(lru.finalizer, evictions)
164 161
    return lru
165 162
end
166 163
@@ -170,7 +167,7 @@
Loading
170 167
    while lru.currentsize > lru.maxsize
171 168
        key = pop!(lru.keyset)
172 169
        v, n, s = pop!(lru.dict, key)
173 -
        if lru.eviction_callback !== _no_callback
170 +
        if lru.finalizer !== nothing
174 171
            push!(evictions, (key, v))
175 172
        end
176 173
        lru.currentsize -= s
@@ -183,57 +180,54 @@
Loading
183 180
    lock(lru.lock) do
184 181
        _unsafe_resize!(lru, evictions, maxsize)
185 182
    end
186 -
    _notify_evictions!(lru.eviction_callback, evictions)
183 +
    _finalize_evictions!(lru.finalizer, evictions)
187 184
    return lru
188 185
end
189 186
190 187
function Base.delete!(lru::LRU{K, V}, key) where {K, V}
191 -
    evictions = Tuple{K, V}[]
192 -
    lock(lru.lock) do
188 +
    v = lock(lru.lock) do
193 189
        v, n, s = pop!(lru.dict, key)
194 -
        if lru.eviction_callback !== _no_callback
195 -
            push!(evictions, (key, v))
196 -
        end
197 190
        lru.currentsize -= s
198 191
        _delete!(lru.keyset, n)
192 +
        return v
193 +
    end
194 +
    if lru.finalizer !== nothing
195 +
        lru.finalizer(key, v)
199 196
    end
200 -
    _notify_evictions!(lru.eviction_callback, evictions)
201 197
    return lru
202 198
end
203 199
function Base.pop!(lru::LRU{K, V}, key) where {K, V}
204 -
    evictions = Tuple{K, V}[]
205 -
    v = lock(lru.lock) do
200 +
    (key, v) = lock(lru.lock) do
206 201
        v, n, s = pop!(lru.dict, key)
207 -
        if lru.eviction_callback !== _no_callback
208 -
            push!(evictions, (key, v))
209 -
        end
210 202
        lru.currentsize -= s
211 203
        _delete!(lru.keyset, n)
212 -
        return v
204 +
        return (key, v)
205 +
    end
206 +
    if lru.finalizer !== nothing
207 +
        lru.finalizer(key, v)
213 208
    end
214 -
    _notify_evictions!(lru.eviction_callback, evictions)
215 209
    return v
216 210
end
217 211
218 212
function Base.empty!(lru::LRU{K, V}) where {K, V}
219 213
    evictions = Tuple{K, V}[]
220 214
    lock(lru.lock) do
221 -
        if lru.eviction_callback === _no_callback
215 +
        if lru.finalizer === nothing
222 216
            lru.currentsize = 0
223 217
            empty!(lru.dict)
224 218
            empty!(lru.keyset)
225 219
        else
220 +
            sizehint!(evictions, length(lru))
226 221
            _unsafe_resize!(lru, evictions, 0)
227 222
        end
228 223
    end
229 -
    _notify_evictions!(lru.eviction_callback, evictions)
224 +
    _finalize_evictions!(lru.finalizer, evictions)
230 225
    return lru
231 226
end
232 227
233 -
function _notify_evictions!(callback, evictions)
234 -
    while !isempty(evictions)
235 -
        key, value = pop!(evictions)
236 -
        callback(key, value)
228 +
function _finalize_evictions!(finalizer, evictions)
229 +
    for (key, value) in evictions
230 +
        finalizer(key, value)
237 231
    end
238 232
    return
239 233
end
Files Coverage
src 76.42%
Project Totals (2 files) 76.42%
Notifications are pending CI completion. Waiting for GitHub's status webhook to queue notifications. Push notifications now.
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading