Skip to content

Commit

Permalink
Add test for concurrent compile() and TimeZone construction.
Browse files Browse the repository at this point in the history
Add comments
  • Loading branch information
NHDaly committed Aug 19, 2021
1 parent 188795f commit 86fae9d
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 26 deletions.
4 changes: 4 additions & 0 deletions src/types/timezone.jl
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Thread-local TimeZone cache, which caches time zones _per thread_, allowing thread-safe
# caching. Note that this means the cache will grow in size, and may store redundant objects
# accross multiple threads, but this extra space usage allows for fast, lock-free access
# to the cache, while still being thread-safe.
const THREAD_TZ_CACHES = Dict{String,Tuple{TimeZone,Class}}[]

# Based upon the thread-safe Global RNG implementation in the Random stdlib:
Expand Down
68 changes: 42 additions & 26 deletions test/thread-safety.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,55 @@ using Test
@assert Threads.nthreads() > 1 "This system does not support multiple threads, so the thread-safety tests cannot be run."
function create_zdt(year, month, day, tz_name)
ZonedDateTime(DateTime(year, month, day), TimeZone(tz_name))
end
function cycle_zdts()
return [
try
create_zdt(year, month, day, tz_name)
catch e
e isa Union{ArgumentError,NonExistentTimeError} || rethrow()
nothing
@testset "Multithreaded TimeZone brute force test" begin
function create_zdt(year, month, day, tz_name)
ZonedDateTime(DateTime(year, month, day), TimeZone(tz_name))
end
function cycle_zdts()
return [
try
create_zdt(year, month, day, tz_name)
catch e
# Ignore ZonedDateTimes that aren't valid
e isa Union{ArgumentError,AmbiguousTimeError,NonExistentTimeError} || rethrow()
nothing
end
for year in 2000:2020
for month in 1:5
for day in 10:15
for tz_name in timezone_names()
]
end
outputs = Channel(Inf)
@sync begin
for _ in 1:15
Threads.@spawn begin
put!(outputs, cycle_zdts())
end
end
for year in 2000:2020
for month in 1:5
for day in 10:15
for tz_name in timezone_names()
]
end
close(outputs)
tzs = collect(outputs)
# Test that every Task produced the same result
allsame(x) = all(y -> y == first(x), x)
@test allsame(tzs)
end
const outputs = Channel(Inf)
@sync begin
for _ in 1:15
#----------------------------------------------------
@testset "Interleaved compile() and TimeZone construction" begin
@sync for i in 1:20
if (i % 5 == 0)
TimeZones.TZData.compile()
end
Threads.@spawn begin
put!(outputs, cycle_zdts())
TimeZone("US/Eastern", TimeZones.Class(:LEGACY))
end
end
end
close(outputs)
const tzs = collect(outputs)
# Test that every Task produced the same result
allsame(x) = all(y -> y == first(x), x)
@test allsame(tzs)
"""

@info "Running Thread Safety tests"
Expand Down

0 comments on commit 86fae9d

Please sign in to comment.