@@ -127,8 +127,11 @@ function _trywait(t::Union{Timer, AsyncCondition})
127127 t isa Timer || Core. Intrinsics. atomic_fence (:acquire_release )
128128 else
129129 if ! isopen (t)
130- close (t) # wait for the close to complete
131- return false
130+ set = t. set
131+ if ! set
132+ close (t) # wait for the close to complete
133+ return false
134+ end
132135 end
133136 iolock_begin ()
134137 set = t. set
@@ -151,7 +154,7 @@ function _trywait(t::Union{Timer, AsyncCondition})
151154 end
152155 iolock_end ()
153156 end
154- @atomic :monotonic t. set = false
157+ @atomic :monotonic t. set = false # if there are multiple waiters, an unspecified number may short-circuit past here
155158 return set
156159end
157160
@@ -161,14 +164,14 @@ function wait(t::Union{Timer, AsyncCondition})
161164end
162165
163166
164- isopen (t:: Union{Timer, AsyncCondition} ) = t . isopen && t. handle != C_NULL
167+ isopen (t:: Union{Timer, AsyncCondition} ) = @atomic :acquire t. isopen
165168
166169function close (t:: Union{Timer, AsyncCondition} )
167- t. handle == C_NULL && return # short-circuit path
170+ t. handle == C_NULL && ! t . isopen && return # short-circuit path, :monotonic
168171 iolock_begin ()
169172 if t. handle != C_NULL
170173 if t. isopen
171- @atomic :monotonic t. isopen = false
174+ @atomic :release t. isopen = false
172175 ccall (:jl_close_uv , Cvoid, (Ptr{Cvoid},), t)
173176 end
174177 # implement _trywait here without the auto-reset function, just waiting for the final close signal
@@ -186,6 +189,8 @@ function close(t::Union{Timer, AsyncCondition})
186189 unlock (t. cond)
187190 unpreserve_handle (t)
188191 end
192+ elseif t. isopen
193+ @atomic :release t. isopen = false
189194 end
190195 iolock_end ()
191196 nothing
@@ -198,8 +203,8 @@ function uvfinalize(t::Union{Timer, AsyncCondition})
198203 if t. handle != C_NULL
199204 disassociate_julia_struct (t. handle) # not going to call the usual close hooks anymore
200205 if t. isopen
201- @atomic :monotonic t. isopen = false
202- ccall (:jl_close_uv , Cvoid, (Ptr{Cvoid},), t. handle)
206+ @atomic :release t. isopen = false
207+ ccall (:jl_close_uv , Cvoid, (Ptr{Cvoid},), t. handle) # this will call Libc.free
203208 end
204209 @atomic :monotonic t. handle = C_NULL
205210 notify (t. cond, false )
214219function _uv_hook_close (t:: Union{Timer, AsyncCondition} )
215220 lock (t. cond)
216221 try
217- @atomic :monotonic t. isopen = false
218- Libc. free (@atomicswap :monotonic t. handle = C_NULL )
222+ handle = t. handle
223+ @atomic :release t. isopen = false
224+ @atomic :monotonic t. handle = C_NULL
225+ Libc. free (handle)
219226 notify (t. cond, false )
220227 finally
221228 unlock (t. cond)
@@ -243,7 +250,7 @@ function uv_timercb(handle::Ptr{Cvoid})
243250 if ccall (:uv_timer_get_repeat , UInt64, (Ptr{Cvoid},), t) == 0
244251 # timer is stopped now
245252 if t. isopen
246- @atomic :monotonic t. isopen = false
253+ @atomic :release t. isopen = false
247254 ccall (:jl_close_uv , Cvoid, (Ptr{Cvoid},), t)
248255 end
249256 end
0 commit comments