Skip to content

Commit bcc885c

Browse files
topolarityKristofferC
authored andcommitted
OncePerX: Improve initializer type for DataType constructors (#58265)
Generalized from JuliaData/Parsers.jl#197 (cherry picked from commit 1f18391)
1 parent 31b0930 commit bcc885c

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

base/lock.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,9 @@ mutable struct OncePerProcess{T, F} <: Function
705705
return once
706706
end
707707
end
708+
OncePerProcess{T}(initializer::Type{U}) where {T, U} = OncePerProcess{T, Type{U}}(initializer)
708709
OncePerProcess{T}(initializer::F) where {T, F} = OncePerProcess{T, F}(initializer)
710+
OncePerProcess(initializer::Type{U}) where U = OncePerProcess{Base.promote_op(initializer), Type{U}}(initializer)
709711
OncePerProcess(initializer) = OncePerProcess{Base.promote_op(initializer), typeof(initializer)}(initializer)
710712
@inline function (once::OncePerProcess{T,F})() where {T,F}
711713
state = (@atomic :acquire once.state)
@@ -812,7 +814,9 @@ mutable struct OncePerThread{T, F} <: Function
812814
return once
813815
end
814816
end
817+
OncePerThread{T}(initializer::Type{U}) where {T, U} = OncePerThread{T,Type{U}}(initializer)
815818
OncePerThread{T}(initializer::F) where {T, F} = OncePerThread{T,F}(initializer)
819+
OncePerThread(initializer::Type{U}) where U = OncePerThread{Base.promote_op(initializer), Type{U}}(initializer)
816820
OncePerThread(initializer) = OncePerThread{Base.promote_op(initializer), typeof(initializer)}(initializer)
817821
@inline (once::OncePerThread{T,F})() where {T,F} = once[Threads.threadid()]
818822
@inline function getindex(once::OncePerThread{T,F}, tid::Integer) where {T,F}
@@ -931,8 +935,10 @@ false
931935
mutable struct OncePerTask{T, F} <: Function
932936
const initializer::F
933937

938+
OncePerTask{T}(initializer::Type{U}) where {T, U} = new{T,Type{U}}(initializer)
934939
OncePerTask{T}(initializer::F) where {T, F} = new{T,F}(initializer)
935940
OncePerTask{T,F}(initializer::F) where {T, F} = new{T,F}(initializer)
941+
OncePerTask(initializer::Type{U}) where U = new{Base.promote_op(initializer), Type{U}}(initializer)
936942
OncePerTask(initializer) = new{Base.promote_op(initializer), typeof(initializer)}(initializer)
937943
end
938944
@inline function (once::OncePerTask{T,F})() where {T,F}

test/threads.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,12 @@ let once = OncePerProcess(() -> return [nothing])
447447
@atomic once.state = 0x01
448448
@test x === once()
449449
end
450+
let once1 = OncePerProcess(BigFloat), once2 = OncePerProcess{BigFloat}(BigFloat)
451+
# Using a type as a constructor should create a OncePerProcess with
452+
# Type{...} as its initializer (rather than DataType)
453+
@test typeof(once1) <: OncePerProcess{BigFloat,Type{BigFloat}}
454+
@test typeof(once2) <: OncePerProcess{BigFloat,Type{BigFloat}}
455+
end
450456
let once = OncePerProcess{Int}(() -> error("expected"))
451457
@test_throws ErrorException("expected") once()
452458
@test_throws ErrorException("OncePerProcess initializer failed previously") once()
@@ -551,6 +557,12 @@ let e = Base.Event(true),
551557
@test_throws ArgumentError once[-1]
552558

553559
end
560+
let once1 = OncePerThread(BigFloat), once2 = OncePerThread{BigFloat}(BigFloat)
561+
# Using a type as a constructor should create a OncePerThread with
562+
# Type{...} as its initializer (rather than DataType)
563+
@test typeof(once1) <: OncePerThread{BigFloat,Type{BigFloat}}
564+
@test typeof(once2) <: OncePerThread{BigFloat,Type{BigFloat}}
565+
end
554566
let once = OncePerThread{Int}(() -> error("expected"))
555567
@test_throws ErrorException("expected") once()
556568
@test_throws ErrorException("OncePerThread initializer failed previously") once()
@@ -563,6 +575,12 @@ let once = OncePerTask(() -> return [nothing])
563575
delete!(task_local_storage(), once)
564576
@test x !== once() === once()
565577
end
578+
let once1 = OncePerTask(BigFloat), once2 = OncePerTask{BigFloat}(BigFloat)
579+
# Using a type as a constructor should create a OncePerTask with
580+
# Type{...} as its initializer (rather than DataType)
581+
@test typeof(once1) <: OncePerTask{BigFloat,Type{BigFloat}}
582+
@test typeof(once2) <: OncePerTask{BigFloat,Type{BigFloat}}
583+
end
566584
let once = OncePerTask{Int}(() -> error("expected"))
567585
@test_throws ErrorException("expected") once()
568586
@test_throws ErrorException("expected") once()

0 commit comments

Comments
 (0)