@@ -43,13 +43,22 @@ the async condition object itself.
4343"""
4444function AsyncCondition (cb:: Function )
4545 async = AsyncCondition ()
46- t = @task while _trywait (async)
47- cb (async)
48- isopen (async) || return
46+ t = @task begin
47+ unpreserve_handle (async)
48+ while _trywait (async)
49+ cb (async)
50+ isopen (async) || return
51+ end
52+ end
53+ # here we are mimicking parts of _trywait, in coordination with task `t`
54+ preserve_handle (async)
55+ @lock async. cond begin
56+ if async. set
57+ schedule (t)
58+ else
59+ _wait2 (async. cond, t)
60+ end
4961 end
50- lock (async. cond)
51- _wait2 (async. cond, t)
52- unlock (async. cond)
5362 return async
5463end
5564
@@ -103,7 +112,11 @@ unsafe_convert(::Type{Ptr{Cvoid}}, async::AsyncCondition) = async.handle
103112
104113function _trywait (t:: Union{Timer, AsyncCondition} )
105114 set = t. set
106- if ! set
115+ if set
116+ # full barrier now for AsyncCondition
117+ t isa Timer || Core. Intrinsics. atomic_fence (:acquire_release )
118+ else
119+ t. isopen || return false
107120 t. handle == C_NULL && return false
108121 iolock_begin ()
109122 set = t. set
@@ -112,14 +125,12 @@ function _trywait(t::Union{Timer, AsyncCondition})
112125 lock (t. cond)
113126 try
114127 set = t. set
115- if ! set
116- if t. handle != C_NULL
117- iolock_end ()
118- set = wait (t. cond)
119- unlock (t. cond)
120- iolock_begin ()
121- lock (t. cond)
122- end
128+ if ! set && t. isopen && t. handle != C_NULL
129+ iolock_end ()
130+ set = wait (t. cond)
131+ unlock (t. cond)
132+ iolock_begin ()
133+ lock (t. cond)
123134 end
124135 finally
125136 unlock (t. cond)
@@ -255,19 +266,28 @@ julia> begin
255266"""
256267function Timer (cb:: Function , timeout:: Real ; interval:: Real = 0.0 )
257268 timer = Timer (timeout, interval= interval)
258- t = @task while _trywait (timer)
259- try
260- cb (timer)
261- catch err
262- write (stderr , " Error in Timer:\n " )
263- showerror (stderr , err, catch_backtrace ())
264- return
269+ t = @task begin
270+ unpreserve_handle (timer)
271+ while _trywait (timer)
272+ try
273+ cb (timer)
274+ catch err
275+ write (stderr , " Error in Timer:\n " )
276+ showerror (stderr , err, catch_backtrace ())
277+ return
278+ end
279+ isopen (timer) || return
280+ end
281+ end
282+ # here we are mimicking parts of _trywait, in coordination with task `t`
283+ preserve_handle (timer)
284+ @lock timer. cond begin
285+ if timer. set
286+ schedule (t)
287+ else
288+ _wait2 (timer. cond, t)
265289 end
266- isopen (timer) || return
267290 end
268- lock (timer. cond)
269- _wait2 (timer. cond, t)
270- unlock (timer. cond)
271291 return timer
272292end
273293
0 commit comments