@@ -45,13 +45,22 @@ the async condition object itself.
4545"""
4646function AsyncCondition (cb:: Function )
4747 async = AsyncCondition ()
48- t = @task while _trywait (async)
49- cb (async)
50- isopen (async) || return
48+ t = @task begin
49+ unpreserve_handle (async)
50+ while _trywait (async)
51+ cb (async)
52+ isopen (async) || return
53+ end
54+ end
55+ # here we are mimicking parts of _trywait, in coordination with task `t`
56+ preserve_handle (async)
57+ @lock async. cond begin
58+ if async. set
59+ schedule (t)
60+ else
61+ _wait2 (async. cond, t)
62+ end
5163 end
52- lock (async. cond)
53- _wait2 (async. cond, t)
54- unlock (async. cond)
5564 return async
5665end
5766
@@ -115,6 +124,7 @@ function _trywait(t::Union{Timer, AsyncCondition})
115124 # full barrier now for AsyncCondition
116125 t isa Timer || Core. Intrinsics. atomic_fence (:acquire_release )
117126 else
127+ t. isopen || return false
118128 t. handle == C_NULL && return false
119129 iolock_begin ()
120130 set = t. set
@@ -123,14 +133,12 @@ function _trywait(t::Union{Timer, AsyncCondition})
123133 lock (t. cond)
124134 try
125135 set = t. set
126- if ! set
127- if t. handle != C_NULL
128- iolock_end ()
129- set = wait (t. cond)
130- unlock (t. cond)
131- iolock_begin ()
132- lock (t. cond)
133- end
136+ if ! set && t. isopen && t. handle != C_NULL
137+ iolock_end ()
138+ set = wait (t. cond)
139+ unlock (t. cond)
140+ iolock_begin ()
141+ lock (t. cond)
134142 end
135143 finally
136144 unlock (t. cond)
@@ -266,19 +274,28 @@ julia> begin
266274"""
267275function Timer (cb:: Function , timeout:: Real ; interval:: Real = 0.0 )
268276 timer = Timer (timeout, interval= interval)
269- t = @task while _trywait (timer)
270- try
271- cb (timer)
272- catch err
273- write (stderr , " Error in Timer:\n " )
274- showerror (stderr , err, catch_backtrace ())
275- return
277+ t = @task begin
278+ unpreserve_handle (timer)
279+ while _trywait (timer)
280+ try
281+ cb (timer)
282+ catch err
283+ write (stderr , " Error in Timer:\n " )
284+ showerror (stderr , err, catch_backtrace ())
285+ return
286+ end
287+ isopen (timer) || return
288+ end
289+ end
290+ # here we are mimicking parts of _trywait, in coordination with task `t`
291+ preserve_handle (timer)
292+ @lock timer. cond begin
293+ if timer. set
294+ schedule (t)
295+ else
296+ _wait2 (timer. cond, t)
276297 end
277- isopen (timer) || return
278298 end
279- lock (timer. cond)
280- _wait2 (timer. cond, t)
281- unlock (timer. cond)
282299 return timer
283300end
284301
0 commit comments