Skip to content

Commit ebd85bf

Browse files
authored
task_local_storage (#15)
1 parent 6a01673 commit ebd85bf

File tree

4 files changed

+32
-42
lines changed

4 files changed

+32
-42
lines changed

src/AdaptivePredicates.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export orient2, orient3, incircle, insphere
1010
export orient2p, orient3p, incirclep, inspherep
1111

1212
@static if VERSION v"1.11.0-DEV.469"
13-
eval(Meta.parse("public orient2, orient3, incircle, insphere, orient2p, orient3p, incirclep, inspherep, free!"))
13+
eval(Meta.parse("public orient2, orient3, incircle, insphere, orient2p, orient3p, incirclep, inspherep"))
1414
end
1515

1616
end # module

src/caches.jl

Lines changed: 21 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,47 +9,26 @@ struct CacheKey{T}
99
id::UInt8
1010
end
1111

12-
const CacheLock = Base.Threads.SpinLock()
12+
struct APMarker{T} end # Avoid collisions with other packages using the task_local_storage
13+
14+
const APCache{T} = Dict{CacheKey{T},Vec{T}}
1315

14-
const TASK_LOCAL_F64CACHE = Dict{Task,Dict{CacheKey{Float64},Vec{Float64}}}()
15-
const TASK_LOCAL_F32CACHE = Dict{Task,Dict{CacheKey{Float32},Vec{Float32}}}()
16-
@inline TASK_LOCAL_CACHE(::Type{Float64}) = TASK_LOCAL_F64CACHE
17-
@inline TASK_LOCAL_CACHE(::Type{Float32}) = TASK_LOCAL_F32CACHE
1816
@inline function task_local_cache(::Type{T}) where {T}
19-
tls = TASK_LOCAL_CACHE(T)
20-
t = current_task()
21-
if haskey(tls, t)
22-
return tls[t]
23-
else
24-
d = Dict{CacheKey{T},Vec{T}}()
25-
lock(CacheLock) do
26-
tls[t] = d
27-
end
28-
return tls[t]
29-
end
17+
tls = get!(task_local_storage(), APMarker{T}()) do
18+
APCache{T}()
19+
end::APCache{T}
20+
return tls::APCache{T}
3021
end
3122

32-
"""
33-
free!()
34-
35-
Empties the caches used for computing the predicates.
36-
"""
37-
free!() = (empty!(TASK_LOCAL_F64CACHE); empty!(TASK_LOCAL_F32CACHE))
38-
39-
@inline cache_eltype(::Dict{CacheKey{Float64},Vec{Float64}}) = Float64
40-
@inline cache_eltype(::Dict{CacheKey{Float32},Vec{Float32}}) = Float32
4123

42-
@inline function get_cache!(tls, size, id)
43-
T = cache_eltype(tls)
24+
@inline function get_cache!(tls::APCache{T}, size, id) where {T}
4425
cache::Vec{T} = get!(tls, CacheKey{T}(size, id)) do
4526
Vec{T}(zeros(T, Int(size))) # Memory{T}(undef, Int(size)) has weird concurrency issues sometimes?
4627
end
4728
return cache::Vec{T}
4829
end
4930

50-
abstract type AbstractCache{T} end
51-
52-
struct Orient2Cache{T} <: AbstractCache{T}
31+
struct Orient2Cache{T}
5332
h4::NTuple{4,T}
5433
h8::NTuple{8,T}
5534
h12::NTuple{12,T}
@@ -63,7 +42,7 @@ end
6342
return Orient2Cache{T}(h4, h8, h12, h16)
6443
end
6544

66-
struct Orient3Cache{T} <: AbstractCache{T}
45+
struct Orient3Cache{T}
6746
h4::NTuple{4,T}
6847
h8::NTuple{8,T}
6948
h12::NTuple{12,T}
@@ -83,6 +62,9 @@ struct Orient3Cache{T} <: AbstractCache{T}
8362
end
8463
@inline function Orient3Cache{T}() where {T}
8564
tls = task_local_cache(T)
65+
return Orient3Cache{T}(tls)
66+
end
67+
@inline function Orient3Cache{T}(tls::APCache{T}) where {T}
8668
h4 = ntuple(_ -> zero(T), Val(4))
8769
h8 = ntuple(_ -> zero(T), Val(8))
8870
h12 = ntuple(_ -> zero(T), Val(12))
@@ -105,7 +87,7 @@ end
10587
)
10688
end
10789

108-
struct IncircleCache{T} <: AbstractCache{T}
90+
struct IncircleCache{T}
10991
h4::NTuple{4,T}
11092
h8::NTuple{8,T}
11193
h12::NTuple{12,T}
@@ -137,6 +119,9 @@ struct IncircleCache{T} <: AbstractCache{T}
137119
end
138120
@inline function IncircleCache{T}() where {T}
139121
tls = task_local_cache(T)
122+
return IncircleCache{T}(tls)
123+
end
124+
@inline function IncircleCache{T}(tls::APCache{T}) where {T}
140125
h4 = ntuple(_ -> zero(T), Val(4))
141126
h8 = ntuple(_ -> zero(T), Val(8))
142127
h12 = ntuple(_ -> zero(T), Val(12))
@@ -174,7 +159,7 @@ end
174159
)
175160
end
176161

177-
struct InsphereCache{T} <: AbstractCache{T}
162+
struct InsphereCache{T}
178163
h4::NTuple{4,T}
179164
h8::NTuple{8,T}
180165
h12::NTuple{12,T}
@@ -238,6 +223,9 @@ struct InsphereCache{T} <: AbstractCache{T}
238223
end
239224
@inline function InsphereCache{T}() where {T}
240225
tls = task_local_cache(T)
226+
return InsphereCache{T}(tls)
227+
end
228+
@inline function InsphereCache{T}(tls::APCache{T}) where {T}
241229
h4 = ntuple(_ -> zero(T), Val(4))
242230
h8 = ntuple(_ -> zero(T), Val(8))
243231
h12 = ntuple(_ -> zero(T), Val(12))

test/Project.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
[deps]
2+
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
23
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
34
ExactPredicates = "429591f6-91af-11e9-00e2-59fbe8cec110"
45
Supposition = "5a0628fe-1738-4658-9b6d-0b7605a9755b"
56
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
7+
8+
[compat]
9+
Aqua = "0.8.7"

test/runtests.jl

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ using Test
33
using Supposition
44
using BenchmarkTools
55
import ExactPredicates: ExactPredicates
6+
using Aqua
7+
8+
@testset "Aqua" begin
9+
Aqua.test_all(AdaptivePredicates)
10+
end
11+
612
const AP = AdaptivePredicates
713
cd("original") do
814
include("compile.jl")
@@ -194,12 +200,4 @@ setup_insphere(T) = ntuple(_ -> (_rand(T), _rand(T), _rand(T)), 5)
194200
@test iszero(@ballocated incircle(args...) setup = (args = setup_incircle(Float32)))
195201
@test iszero(@ballocated insphere(args...) setup = (args = setup_insphere(Float64)))
196202
@test iszero(@ballocated insphere(args...) setup = (args = setup_insphere(Float32)))
197-
end
198-
199-
@testset "free!" begin
200-
F64C = AP.TASK_LOCAL_F64CACHE
201-
F32C = AP.TASK_LOCAL_F32CACHE
202-
@test !isempty(F64C) && !isempty(F32C)
203-
AP.free!()
204-
@test isempty(F64C) && isempty(F32C)
205203
end

0 commit comments

Comments
 (0)