Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: JuliaLang/julia
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: e47af02127e4d4fc2d6eb22689d6b49a4ca89941
Choose a base ref
..
head repository: JuliaLang/julia
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 2b1d8acc84c0661b7e209b3ff1529ae4fea9ee67
Choose a head ref
Showing with 54 additions and 16 deletions.
  1. +0 −1 base/condition.jl
  2. +21 −12 base/loading.jl
  3. +1 −0 base/lock.jl
  4. +4 −0 base/locks-mt.jl
  5. +3 −0 stdlib/Random/src/RNGs.jl
  6. +5 −2 stdlib/Random/src/Random.jl
  7. +3 −0 stdlib/Random/test/runtests.jl
  8. +2 −1 test/precompile.jl
  9. +15 −0 test/threads_exec.jl
1 change: 0 additions & 1 deletion base/condition.jl
Original file line number Diff line number Diff line change
@@ -22,7 +22,6 @@ function trylock end
function islocked end
unlockall(l::AbstractLock) = unlock(l) # internal function for implementing `wait`
relockall(l::AbstractLock, token::Nothing) = lock(l) # internal function for implementing `wait`
assert_havelock(l::AbstractLock) = assert_havelock(l, Threads.threadid())
assert_havelock(l::AbstractLock, tid::Integer) =
(islocked(l) && tid == Threads.threadid()) ? nothing : concurrency_violation()
assert_havelock(l::AbstractLock, tid::Task) =
33 changes: 21 additions & 12 deletions base/loading.jl
Original file line number Diff line number Diff line change
@@ -1222,6 +1222,18 @@ function create_expr_cache(input::String, output::String, concrete_deps::typeof(
return io
end

function compilecache_path(pkg::PkgId)::String
entrypath, entryfile = cache_file_entry(pkg)
cachepath = joinpath(DEPOT_PATH[1], entrypath)
isdir(cachepath) || mkpath(cachepath)
if pkg.uuid === nothing
abspath(cachepath, entryfile) * ".ji"
else
project_precompile_slug = slug(_crc32c(something(Base.active_project(), "")), 5)
abspath(cachepath, string(entryfile, "_", project_precompile_slug, ".ji"))
end
end

"""
Base.compilecache(module::PkgId)
@@ -1240,19 +1252,16 @@ const MAX_NUM_PRECOMPILE_FILES = 10

function compilecache(pkg::PkgId, path::String)
# decide where to put the resulting cache file
entrypath, entryfile = cache_file_entry(pkg)
cachepath = joinpath(DEPOT_PATH[1], entrypath)
isdir(cachepath) || mkpath(cachepath)
if pkg.uuid === nothing
cachefile = abspath(cachepath, entryfile) * ".ji"
else
candidates = filter!(x -> startswith(x, entryfile * "_"), readdir(cachepath))
if length(candidates) >= MAX_NUM_PRECOMPILE_FILES
idx = findmin(mtime.(joinpath.(cachepath, candidates)))[2]
rm(joinpath(cachepath, candidates[idx]))
cachefile = compilecache_path(pkg)
# prune the directory with cache files
if pkg.uuid !== nothing
cachepath = dirname(cachefile)
entrypath, entryfile = cache_file_entry(pkg)
cachefiles = filter!(x -> startswith(x, entryfile * "_"), readdir(cachepath))
if length(cachefiles) >= MAX_NUM_PRECOMPILE_FILES
idx = findmin(mtime.(joinpath.(cachepath, cachefiles)))[2]
rm(joinpath(cachepath, cachefiles[idx]))
end
project_precompile_slug = slug(_crc32c(something(Base.active_project(), "")), 5)
cachefile = abspath(cachepath, string(entryfile, "_", project_precompile_slug, ".ji"))
end
# build up the list of modules that we want the precompile process to preserve
concrete_deps = copy(_concrete_dependencies)
1 change: 1 addition & 0 deletions base/lock.jl
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@ mutable struct ReentrantLock <: AbstractLock
ReentrantLock() = new(nothing, GenericCondition{Threads.SpinLock}(), 0)
end

assert_havelock(l::ReentrantLock) = assert_havelock(l, l.locked_by)

"""
islocked(lock) -> Status (Boolean)
4 changes: 4 additions & 0 deletions base/locks-mt.jl
Original file line number Diff line number Diff line change
@@ -30,6 +30,10 @@ struct SpinLock <: AbstractLock
SpinLock() = new(Atomic{Int}(0))
end

# Note: this cannot assert that the lock is held by the correct thread, because we do not
# track which thread locked it. Users beware.
Base.assert_havelock(l::SpinLock) = islocked(l) ? nothing : concurrency_violation()

function lock(l::SpinLock)
while true
if l.handle[] == 0
3 changes: 3 additions & 0 deletions stdlib/Random/src/RNGs.jl
Original file line number Diff line number Diff line change
@@ -313,6 +313,9 @@ struct _GLOBAL_RNG <: AbstractRNG
global const GLOBAL_RNG = _GLOBAL_RNG.instance
end

# GLOBAL_RNG currently represents a MersenneTwister
typeof_rng(::_GLOBAL_RNG) = MersenneTwister

copy!(dst::MersenneTwister, ::_GLOBAL_RNG) = copy!(dst, default_rng())
copy!(::_GLOBAL_RNG, src::MersenneTwister) = copy!(default_rng(), src)
copy(::_GLOBAL_RNG) = copy(default_rng())
7 changes: 5 additions & 2 deletions stdlib/Random/src/Random.jl
Original file line number Diff line number Diff line change
@@ -136,8 +136,11 @@ the amount of precomputation, if applicable.
*types* and *values*, respectively. [`Random.SamplerSimple`](@ref) can be used to store
pre-computed values without defining extra types for only this purpose.
"""
Sampler(rng::AbstractRNG, x, r::Repetition=Val(Inf)) = Sampler(typeof(rng), x, r)
Sampler(rng::AbstractRNG, ::Type{X}, r::Repetition=Val(Inf)) where {X} = Sampler(typeof(rng), X, r)
Sampler(rng::AbstractRNG, x, r::Repetition=Val(Inf)) = Sampler(typeof_rng(rng), x, r)
Sampler(rng::AbstractRNG, ::Type{X}, r::Repetition=Val(Inf)) where {X} =
Sampler(typeof_rng(rng), X, r)

typeof_rng(rng::AbstractRNG) = typeof(rng)

Sampler(::Type{<:AbstractRNG}, sp::Sampler, ::Repetition) =
throw(ArgumentError("Sampler for this object is not defined"))
3 changes: 3 additions & 0 deletions stdlib/Random/test/runtests.jl
Original file line number Diff line number Diff line change
@@ -770,4 +770,7 @@ end
B = fill!(B, 1.0)
@test rand!(GLOBAL_RNG, A, x) === A == rand!(mt, B, x) === B
end
# issue #33170
@test Sampler(GLOBAL_RNG, 2:4, Val(1)) isa SamplerRangeFast
@test Sampler(GLOBAL_RNG, 2:4, Val(Inf)) isa SamplerRangeFast
end
3 changes: 2 additions & 1 deletion test/precompile.jl
Original file line number Diff line number Diff line change
@@ -332,7 +332,8 @@ try
end
""")

Base.compilecache(Base.PkgId("FooBar"))
cachefile = Base.compilecache(Base.PkgId("FooBar"))
@test cachefile == Base.compilecache_path(Base.PkgId("FooBar"))
@test isfile(joinpath(cachedir, "FooBar.ji"))
@test Base.stale_cachefile(FooBar_file, joinpath(cachedir, "FooBar.ji")) isa Vector
@test !isdefined(Main, :FooBar)
15 changes: 15 additions & 0 deletions test/threads_exec.jl
Original file line number Diff line number Diff line change
@@ -151,6 +151,21 @@ end
threaded_gc_locked(SpinLock)
threaded_gc_locked(Threads.ReentrantLock)

# Issue 33159
# Make sure that a Threads.Condition can't be used without being locked, on any thread.
@testset "Threads.Conditions must be locked" begin
c = Threads.Condition()
@test_throws Exception notify(c)
@test_throws Exception wait(c)

# If it's locked, but on the wrong thread, it should still throw an exception
lock(c)
@test_throws Exception fetch(@async notify(c))
@test_throws Exception fetch(@async notify(c, all=false))
@test_throws Exception fetch(@async wait(c))
unlock(c)
end

# Issue 14726
# Make sure that eval'ing in a different module doesn't mess up other threads
orig_curmodule14726 = @__MODULE__