@@ -127,8 +127,11 @@ function _trywait(t::Union{Timer, AsyncCondition})
127
127
t isa Timer || Core. Intrinsics. atomic_fence (:acquire_release )
128
128
else
129
129
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
132
135
end
133
136
iolock_begin ()
134
137
set = t. set
@@ -151,7 +154,7 @@ function _trywait(t::Union{Timer, AsyncCondition})
151
154
end
152
155
iolock_end ()
153
156
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
155
158
return set
156
159
end
157
160
@@ -161,14 +164,14 @@ function wait(t::Union{Timer, AsyncCondition})
161
164
end
162
165
163
166
164
- isopen (t:: Union{Timer, AsyncCondition} ) = t . isopen && t. handle != C_NULL
167
+ isopen (t:: Union{Timer, AsyncCondition} ) = @atomic :acquire t. isopen
165
168
166
169
function 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
168
171
iolock_begin ()
169
172
if t. handle != C_NULL
170
173
if t. isopen
171
- @atomic :monotonic t. isopen = false
174
+ @atomic :release t. isopen = false
172
175
ccall (:jl_close_uv , Cvoid, (Ptr{Cvoid},), t)
173
176
end
174
177
# 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})
186
189
unlock (t. cond)
187
190
unpreserve_handle (t)
188
191
end
192
+ elseif t. isopen
193
+ @atomic :release t. isopen = false
189
194
end
190
195
iolock_end ()
191
196
nothing
@@ -198,8 +203,8 @@ function uvfinalize(t::Union{Timer, AsyncCondition})
198
203
if t. handle != C_NULL
199
204
disassociate_julia_struct (t. handle) # not going to call the usual close hooks anymore
200
205
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
203
208
end
204
209
@atomic :monotonic t. handle = C_NULL
205
210
notify (t. cond, false )
214
219
function _uv_hook_close (t:: Union{Timer, AsyncCondition} )
215
220
lock (t. cond)
216
221
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)
219
226
notify (t. cond, false )
220
227
finally
221
228
unlock (t. cond)
@@ -243,7 +250,7 @@ function uv_timercb(handle::Ptr{Cvoid})
243
250
if ccall (:uv_timer_get_repeat , UInt64, (Ptr{Cvoid},), t) == 0
244
251
# timer is stopped now
245
252
if t. isopen
246
- @atomic :monotonic t. isopen = false
253
+ @atomic :release t. isopen = false
247
254
ccall (:jl_close_uv , Cvoid, (Ptr{Cvoid},), t)
248
255
end
249
256
end
0 commit comments