Skip to content

Commit c5dd2bc

Browse files
authored
Fix concurrenty issue with global MC cache (#203)
* Fix concurrency bug * Add a docstring * Convert GlobalMCCache docstring to just a comment
1 parent 7fbac1c commit c5dd2bc

File tree

3 files changed

+23
-2
lines changed

3 files changed

+23
-2
lines changed

HISTORY.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 0.9.7
2+
3+
Fix a concurrency bug, where Libtask would sometimes crash with a "Multiple concurrent writes to Dict detected!" error when TapedTasks were being executed concurrently.
4+
15
# 0.9.6
26

37
Add support for Julia v1.12.

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ uuid = "6f1fad26-d15e-5dc8-ae53-837a1d7b8c9f"
33
license = "MIT"
44
desc = "Tape based task copying in Turing"
55
repo = "https://github.com/TuringLang/Libtask.jl.git"
6-
version = "0.9.6"
6+
version = "0.9.7"
77

88
[deps]
99
MistyClosures = "dbe65cb8-6be2-42dd-bbc5-4196aaced4f4"

src/copyable_task.jl

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,24 @@ struct CacheKey
113113
key::Any
114114
end
115115

116-
const mc_cache = Dict{CacheKey,MistyClosure}()
116+
# A cache for holding MistyClosures, keyed by CacheKey.
117+
# The reason to have a type for this, rather than just a global const
118+
# Dict{CacheKey,MistyClosure}, is thread-safety. The global cache is written to when new
119+
# TapedTasks are compiled, and if multiple threads are doing this concurrently races might
120+
# occur. This type uses a ReentrantLock to ensure that any `setindex!` operations are
121+
# atomic, solving the problem.
122+
struct GlobalMCCache
123+
cache::Dict{CacheKey,MistyClosure}
124+
lock::ReentrantLock
125+
126+
GlobalMCCache() = new(Dict{CacheKey,MistyClosure}(), ReentrantLock())
127+
end
128+
129+
Base.haskey(c::GlobalMCCache, key) = haskey(c.cache, key)
130+
Base.getindex(c::GlobalMCCache, key) = getindex(c.cache, key)
131+
Base.setindex!(c::GlobalMCCache, val, key) = @lock c.lock setindex!(c.cache, val, key)
132+
133+
const mc_cache = GlobalMCCache()
117134

118135
"""
119136
TapedTask(taped_globals::Any, f, args...; kwargs...)

0 commit comments

Comments
 (0)