767767
768768
769769# share a lock/condition, since we just need it briefly, so some contention is okay
770- const PerThreadLock = ThreadSynchronizer ()
770+ const PerThreadLock = Threads . SpinLock ()
771771"""
772772 OncePerThread{T}(init::Function)() -> T
773773
@@ -871,7 +871,15 @@ OncePerThread(initializer) = OncePerThread{Base.promote_op(initializer), typeof(
871871 state = @atomic :monotonic ss[tid]
872872 while state == PerStateConcurrent
873873 # lost race, wait for notification this is done running elsewhere
874- wait (PerThreadLock) # wait for initializer to finish without releasing this thread
874+ # without releasing this thread
875+ unlock (PerThreadLock)
876+ while state == PerStateConcurrent
877+ # spin loop until ready
878+ ss = @atomic :acquire once. ss
879+ state = @atomic :monotonic ss[tid]
880+ GC. safepoint ()
881+ end
882+ lock (PerThreadLock)
875883 ss = @atomic :monotonic once. ss
876884 state = @atomic :monotonic ss[tid]
877885 end
@@ -885,7 +893,6 @@ OncePerThread(initializer) = OncePerThread{Base.promote_op(initializer), typeof(
885893 lock (PerThreadLock)
886894 ss = @atomic :monotonic once. ss
887895 @atomic :release ss[tid] = PerStateErrored
888- notify (PerThreadLock)
889896 rethrow ()
890897 end
891898 # store result and notify waiters
@@ -894,7 +901,6 @@ OncePerThread(initializer) = OncePerThread{Base.promote_op(initializer), typeof(
894901 @atomic :release xs[tid] = result
895902 ss = @atomic :monotonic once. ss
896903 @atomic :release ss[tid] = PerStateHasrun
897- notify (PerThreadLock)
898904 elseif state == PerStateErrored
899905 error (" OncePerThread initializer failed previously" )
900906 elseif state != PerStateHasrun
0 commit comments