Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions base/lock.jl
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,9 @@ mutable struct OncePerProcess{T, F} <: Function
return once
end
end
OncePerProcess{T}(initializer::Type{U}) where {T, U} = OncePerProcess{T, Type{U}}(initializer)
OncePerProcess{T}(initializer::F) where {T, F} = OncePerProcess{T, F}(initializer)
OncePerProcess(initializer::Type{U}) where U = OncePerProcess{Base.promote_op(initializer), Type{U}}(initializer)
OncePerProcess(initializer) = OncePerProcess{Base.promote_op(initializer), typeof(initializer)}(initializer)
@inline function (once::OncePerProcess{T,F})() where {T,F}
state = (@atomic :acquire once.state)
Expand Down Expand Up @@ -842,7 +844,9 @@ mutable struct OncePerThread{T, F} <: Function
return once
end
end
OncePerThread{T}(initializer::Type{U}) where {T, U} = OncePerThread{T,Type{U}}(initializer)
OncePerThread{T}(initializer::F) where {T, F} = OncePerThread{T,F}(initializer)
OncePerThread(initializer::Type{U}) where U = OncePerThread{Base.promote_op(initializer), Type{U}}(initializer)
OncePerThread(initializer) = OncePerThread{Base.promote_op(initializer), typeof(initializer)}(initializer)
@inline (once::OncePerThread{T,F})() where {T,F} = once[Threads.threadid()]
@inline function getindex(once::OncePerThread{T,F}, tid::Integer) where {T,F}
Expand Down Expand Up @@ -961,8 +965,10 @@ false
mutable struct OncePerTask{T, F} <: Function
const initializer::F

OncePerTask{T}(initializer::Type{U}) where {T, U} = new{T,Type{U}}(initializer)
OncePerTask{T}(initializer::F) where {T, F} = new{T,F}(initializer)
OncePerTask{T,F}(initializer::F) where {T, F} = new{T,F}(initializer)
OncePerTask(initializer::Type{U}) where U = new{Base.promote_op(initializer), Type{U}}(initializer)
OncePerTask(initializer) = new{Base.promote_op(initializer), typeof(initializer)}(initializer)
end
@inline function (once::OncePerTask{T,F})() where {T,F}
Expand Down
18 changes: 18 additions & 0 deletions test/threads.jl
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,12 @@ let once = OncePerProcess(() -> return [nothing])
@atomic once.state = 0x01
@test x === once()
end
let once1 = OncePerProcess(BigFloat), once2 = OncePerProcess{BigFloat}(BigFloat)
# Using a type as a constructor should create a OncePerProcess with
# Type{...} as its initializer (rather than DataType)
@test typeof(once1) <: OncePerProcess{BigFloat,Type{BigFloat}}
@test typeof(once2) <: OncePerProcess{BigFloat,Type{BigFloat}}
end
let once = OncePerProcess{Int}(() -> error("expected"))
@test_throws ErrorException("expected") once()
@test_throws ErrorException("OncePerProcess initializer failed previously") once()
Expand Down Expand Up @@ -551,6 +557,12 @@ let e = Base.Event(true),
@test_throws ArgumentError once[-1]

end
let once1 = OncePerThread(BigFloat), once2 = OncePerThread{BigFloat}(BigFloat)
# Using a type as a constructor should create a OncePerThread with
# Type{...} as its initializer (rather than DataType)
@test typeof(once1) <: OncePerThread{BigFloat,Type{BigFloat}}
@test typeof(once2) <: OncePerThread{BigFloat,Type{BigFloat}}
end
let once = OncePerThread{Int}(() -> error("expected"))
@test_throws ErrorException("expected") once()
@test_throws ErrorException("OncePerThread initializer failed previously") once()
Expand All @@ -563,6 +575,12 @@ let once = OncePerTask(() -> return [nothing])
delete!(task_local_storage(), once)
@test x !== once() === once()
end
let once1 = OncePerTask(BigFloat), once2 = OncePerTask{BigFloat}(BigFloat)
# Using a type as a constructor should create a OncePerTask with
# Type{...} as its initializer (rather than DataType)
@test typeof(once1) <: OncePerTask{BigFloat,Type{BigFloat}}
@test typeof(once2) <: OncePerTask{BigFloat,Type{BigFloat}}
end
let once = OncePerTask{Int}(() -> error("expected"))
@test_throws ErrorException("expected") once()
@test_throws ErrorException("expected") once()
Expand Down