Skip to content

Commit 676a035

Browse files
committed
Address review comments
1 parent 11cda8c commit 676a035

File tree

1 file changed

+21
-4
lines changed

1 file changed

+21
-4
lines changed

src/independentlylinearizedutils.jl

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,19 @@ us = CachePool(Vector{S}, () -> Vector{S}(undef, num_us); thread_safe=false)
2525
end
2626
end
2727
```
28+
29+
!!! warning "Escaping values"
30+
You must not use an acquired value after you have released it;
31+
the memory may be immediately re-used by some other consumer of
32+
your cache pool. Do not allow the acquired value to escape
33+
outside of the `@with_cache` block, or past a `release!()`.
2834
"""
2935
mutable struct CachePool{T, THREAD_SAFE}
30-
pool::Vector{T}
31-
alloc::Function
36+
const pool::Vector{T}
37+
const alloc::Function
3238
lock::ReentrantLock
3339
num_alloced::Int
40+
num_acquired::Int
3441

3542
function CachePool(T, alloc::F; thread_safe::Bool = true) where {F}
3643
return new{T,Val{thread_safe}}(T[], alloc, ReentrantLock(), 0)
@@ -46,6 +53,7 @@ Returns a cached element of the cache pool, calling `cache.alloc()` if none
4653
are available.
4754
"""
4855
Base.@inline function acquire!(cache::CachePool{T}, _dummy = nothing) where {T}
56+
cache.num_acquired += 1
4957
if isempty(cache.pool)
5058
cache.num_alloced += 1
5159
return cache.alloc()::T
@@ -60,11 +68,17 @@ Returns the value `val` to the cache pool.
6068
"""
6169
Base.@inline function release!(cache::CachePool, val, _dummy = nothing)
6270
push!(cache.pool, val)
71+
cache.num_acquired -= 1
72+
end
73+
74+
function is_fully_released(cache::CachePool, _dummy = nothing)
75+
return cache.num_acquired == 0
6376
end
6477

6578
# Thread-safe versions just sub out to the other methods, using `_dummy` to force correct dispatch
6679
acquire!(cache::ThreadSafeCachePool) = @lock cache.lock acquire!(cache, nothing)
6780
release!(cache::ThreadSafeCachePool, val) = @lock cache.lock release!(cache, val, nothing)
81+
is_fully_released(cache::ThreadSafeCachePool) = @lock cache.lock is_fully_released(cache, nothing)
6882

6983
macro with_cache(cache, name, body)
7084
return quote
@@ -270,8 +284,8 @@ mutable struct IndependentlyLinearizedSolution{T, S, N}
270284
time_mask::BitMatrix
271285

272286
# Temporary object used during construction, will be set to `nothing` at the end.
273-
ilsc::Union{Nothing,IndependentlyLinearizedSolutionChunks{T,S}}
274-
ilsc_cache_pool::Union{Nothing,ThreadSafeCachePool{IndependentlyLinearizedSolutionChunksCache{T,S}}}
287+
ilsc::Union{Nothing,IndependentlyLinearizedSolutionChunks{T,S,N}}
288+
ilsc_cache_pool::Union{Nothing,ThreadSafeCachePool{IndependentlyLinearizedSolutionChunksCache{T,S,N}}}
275289
end
276290
# Helper function to create an ILS wrapped around an in-progress ILSC
277291
function IndependentlyLinearizedSolution(ilsc::IndependentlyLinearizedSolutionChunks{T,S,N}, cache_pool = nothing) where {T,S,N}
@@ -392,14 +406,17 @@ function finish!(ils::IndependentlyLinearizedSolution{T,S}) where {T,S}
392406
# Update our struct, release the `ilsc` and its caches
393407
for t_chunk in ilsc.t_chunks
394408
release!(ilsc.cache.t_chunks, t_chunk)
409+
@assert is_fully_released(ilsc.cache.t_chunks)
395410
end
396411
for u_idx in 1:length(ilsc.u_chunks)
397412
for u_chunk in ilsc.u_chunks[u_idx]
398413
release!(ilsc.cache.u_chunks, u_chunk)
399414
end
415+
@assert is_fully_released(ilsc.cache.u_chunks)
400416
end
401417
for time_mask in ilsc.time_masks
402418
release!(ilsc.cache.time_masks, time_mask)
419+
@assert is_fully_released(ilsc.cache.time_masks)
403420
end
404421
if ils.ilsc_cache_pool !== nothing
405422
release!(ils.ilsc_cache_pool, ilsc.cache)

0 commit comments

Comments
 (0)