767
767
768
768
769
769
# share a lock/condition, since we just need it briefly, so some contention is okay
770
- const PerThreadLock = ThreadSynchronizer ()
770
+ const PerThreadLock = Threads . SpinLock ()
771
771
"""
772
772
OncePerThread{T}(init::Function)() -> T
773
773
@@ -871,7 +871,15 @@ OncePerThread(initializer) = OncePerThread{Base.promote_op(initializer), typeof(
871
871
state = @atomic :monotonic ss[tid]
872
872
while state == PerStateConcurrent
873
873
# 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)
875
883
ss = @atomic :monotonic once. ss
876
884
state = @atomic :monotonic ss[tid]
877
885
end
@@ -885,7 +893,6 @@ OncePerThread(initializer) = OncePerThread{Base.promote_op(initializer), typeof(
885
893
lock (PerThreadLock)
886
894
ss = @atomic :monotonic once. ss
887
895
@atomic :release ss[tid] = PerStateErrored
888
- notify (PerThreadLock)
889
896
rethrow ()
890
897
end
891
898
# store result and notify waiters
@@ -894,7 +901,6 @@ OncePerThread(initializer) = OncePerThread{Base.promote_op(initializer), typeof(
894
901
@atomic :release xs[tid] = result
895
902
ss = @atomic :monotonic once. ss
896
903
@atomic :release ss[tid] = PerStateHasrun
897
- notify (PerThreadLock)
898
904
elseif state == PerStateErrored
899
905
error (" OncePerThread initializer failed previously" )
900
906
elseif state != PerStateHasrun
0 commit comments