797797
798798
799799# share a lock/condition, since we just need it briefly, so some contention is okay
800- const PerThreadLock = ThreadSynchronizer ()
800+ const PerThreadLock = Threads . SpinLock ()
801801"""
802802 OncePerThread{T}(init::Function)() -> T
803803
@@ -901,7 +901,15 @@ OncePerThread(initializer) = OncePerThread{Base.promote_op(initializer), typeof(
901901 state = @atomic :monotonic ss[tid]
902902 while state == PerStateConcurrent
903903 # lost race, wait for notification this is done running elsewhere
904- wait (PerThreadLock) # wait for initializer to finish without releasing this thread
904+ # without releasing this thread
905+ unlock (PerThreadLock)
906+ while state == PerStateConcurrent
907+ # spin loop until ready
908+ ss = @atomic :acquire once. ss
909+ state = @atomic :monotonic ss[tid]
910+ GC. safepoint ()
911+ end
912+ lock (PerThreadLock)
905913 ss = @atomic :monotonic once. ss
906914 state = @atomic :monotonic ss[tid]
907915 end
@@ -915,7 +923,6 @@ OncePerThread(initializer) = OncePerThread{Base.promote_op(initializer), typeof(
915923 lock (PerThreadLock)
916924 ss = @atomic :monotonic once. ss
917925 @atomic :release ss[tid] = PerStateErrored
918- notify (PerThreadLock)
919926 rethrow ()
920927 end
921928 # store result and notify waiters
@@ -924,7 +931,6 @@ OncePerThread(initializer) = OncePerThread{Base.promote_op(initializer), typeof(
924931 @atomic :release xs[tid] = result
925932 ss = @atomic :monotonic once. ss
926933 @atomic :release ss[tid] = PerStateHasrun
927- notify (PerThreadLock)
928934 elseif state == PerStateErrored
929935 error (" OncePerThread initializer failed previously" )
930936 elseif state != PerStateHasrun
0 commit comments