@@ -33,10 +33,7 @@ class ChannelImplWithSignal : public DebuggerId<ChannelImplWithSignal<int>>
3333 RS_DBG (dbg_channel, " channel=%ld | %s | ptr(t)=0x%p | isWait=%d | abstime=%d | closed=%d | popWaiting_=%p | pushWaiting_=%p" ,
3434 id (), __func__, (void *)&t, isWait, !!abstime, closed_, (void *)popWaiting_, (void *)pushWaiting_);
3535
36- if (closed_)
37- return false ;
38-
39- if (pushWaiting_) { // 有push协程在等待, 读出来 & 清理
36+ if (pushWaiting_ && pushWaiting_ != (ConditionVariable*)kClosedWaiting ) { // 有push协程在等待, 读出来 & 清理
4037 t = *pushQ_;
4138 pushQ_ = nullptr ;
4239
@@ -51,6 +48,9 @@ class ChannelImplWithSignal : public DebuggerId<ChannelImplWithSignal<int>>
5148 return true ;
5249 }
5350
51+ if (closed_)
52+ return false ;
53+
5454 if (!isWait) {
5555 RS_DBG (dbg_channel, " channel=%ld | %s | not match && not wait | return false" ,
5656 id (), __func__);
@@ -68,15 +68,16 @@ class ChannelImplWithSignal : public DebuggerId<ChannelImplWithSignal<int>>
6868 id (), __func__);
6969
7070 (void )waiting.wait_until_p (lock, abstime, [&]{ return popWaiting_ != &waiting; });
71- bool ok = popWaiting_ != &waiting;
71+ bool changed = (popWaiting_ != &waiting);
72+ bool ok = changed && popWaiting_ != (ConditionVariable*)kClosedWaiting ;
7273
73- RS_DBG (dbg_channel, " channel=%ld | %s | waked | matched =%d" ,
74- id (), __func__, ok);
74+ RS_DBG (dbg_channel, " channel=%ld | %s | waked | closed=%d | changed=%d | ok =%d" ,
75+ id (), __func__, closed_, changed, ok);
7576
7677 if (ok) {
7778 // 成功
7879 t = std::move (temp); // 对外部T的写操作放到本线程来做, 降低使用难度
79- } else {
80+ } else if (!changed) {
8081 // 超时,清理
8182 popQ_ = nullptr ;
8283 popWaiting_ = nullptr ;
@@ -93,13 +94,13 @@ class ChannelImplWithSignal : public DebuggerId<ChannelImplWithSignal<int>>
9394 RS_DBG (dbg_channel, " channel=%ld | %s | ptr(t)=0x%p | isWait=%d | abstime=%d | closed=%d | popWaiting_=%p | pushWaiting_=%p" ,
9495 id (), __func__, (void *)&t, isWait, !!abstime, closed_, (void *)popWaiting_, (void *)pushWaiting_);
9596
97+ if (closed_)
98+ return false ;
99+
96100 if (!popWaiting_) {
97101 return pop_impl_with_signal_noqueued (t, isWait, abstime, lock);
98102 }
99103
100- if (closed_)
101- return false ;
102-
103104 if (!isWait) {
104105 RS_DBG (dbg_channel, " channel=%ld | %s | pop contended && not wait | return false" ,
105106 id (), __func__);
@@ -119,8 +120,12 @@ class ChannelImplWithSignal : public DebuggerId<ChannelImplWithSignal<int>>
119120 }
120121 }
121122
122- RS_DBG (dbg_channel, " channel=%ld | %s | waked | pop idle" ,
123- id (), __func__);
123+ RS_DBG (dbg_channel, " channel=%ld | %s | waked | closed=%d | pop idle" ,
124+ id (), __func__, closed_);
125+
126+ if (closed_)
127+ return false ;
128+
124129 return pop_impl_with_signal_noqueued (t, isWait, abstime, lock);
125130 }
126131
@@ -132,10 +137,7 @@ class ChannelImplWithSignal : public DebuggerId<ChannelImplWithSignal<int>>
132137 RS_DBG (dbg_channel, " channel=%ld | %s | ptr(t)=0x%p | isWait=%d | abstime=%d | closed=%d | popWaiting_=%p | pushWaiting_=%p" ,
133138 id (), __func__, (void *)&t, isWait, !!abstime, closed_, (void *)popWaiting_, (void *)pushWaiting_);
134139
135- if (closed_)
136- return false ;
137-
138- if (popWaiting_) { // 有pop协程在等待, 写入 & 清理
140+ if (popWaiting_ && popWaiting_ != (ConditionVariable*)kClosedWaiting ) { // 有pop协程在等待, 写入 & 清理
139141 *popQ_ = t;
140142 popQ_ = nullptr ;
141143
@@ -150,6 +152,9 @@ class ChannelImplWithSignal : public DebuggerId<ChannelImplWithSignal<int>>
150152 return true ;
151153 }
152154
155+ if (closed_)
156+ return false ;
157+
153158 if (!isWait) {
154159 RS_DBG (dbg_channel, " channel=%ld | %s | not match && not wait | return false" ,
155160 id (), __func__);
@@ -166,18 +171,20 @@ class ChannelImplWithSignal : public DebuggerId<ChannelImplWithSignal<int>>
166171 id (), __func__);
167172
168173 (void )waiting.wait_until_p (lock, abstime, [&]{ return pushWaiting_ != &waiting; });
169- bool ok = pushWaiting_ != &waiting;
174+ bool changed = (pushWaiting_ != &waiting);
175+ bool ok = changed && pushWaiting_ != (ConditionVariable*)kClosedWaiting ;
170176
171- RS_DBG (dbg_channel, " channel=%ld | %s | waked | matched =%d" ,
172- id (), __func__, ok);
177+ RS_DBG (dbg_channel, " channel=%ld | %s | waked | closed=%d | changed=%d | ok =%d" ,
178+ id (), __func__, closed_, changed, ok);
173179
174180 if (ok) {
175181 // 成功
176- } else {
182+ } else if (!changed) {
177183 // 超时,清理
178184 pushQ_ = nullptr ;
179185 pushWaiting_ = nullptr ;
180186 }
187+
181188 return ok;
182189 }
183190
@@ -194,6 +201,9 @@ class ChannelImplWithSignal : public DebuggerId<ChannelImplWithSignal<int>>
194201 return push_impl_with_signal_noqueued (t, isWait, abstime, lock);
195202 }
196203
204+ if (closed_)
205+ return false ;
206+
197207 if (!isWait) {
198208 RS_DBG (dbg_channel, " channel=%ld | %s | push contended && not wait | return false" ,
199209 id (), __func__);
@@ -213,11 +223,36 @@ class ChannelImplWithSignal : public DebuggerId<ChannelImplWithSignal<int>>
213223 }
214224 }
215225
216- RS_DBG (dbg_channel, " channel=%ld | %s | waked | push idle" ,
217- id (), __func__);
226+ RS_DBG (dbg_channel, " channel=%ld | %s | waked | closed=%d | push idle" ,
227+ id (), __func__, closed_);
228+
229+ if (closed_)
230+ return false ;
231+
218232 return push_impl_with_signal_noqueued (t, isWait, abstime, lock);
219233 }
220234
235+ void impl_with_signal_close (std::unique_lock<Mutex> & lock)
236+ {
237+ long push_wakeup = 0 ;
238+ long pop_wakeup = 0 ;
239+ pushQ_ = nullptr ;
240+ popQ_ = nullptr ;
241+ if (pushWaiting_) {
242+ pushWaiting_->fast_notify_all (lock);
243+ pushWaiting_ = (ConditionVariable*)kClosedWaiting ;
244+ push_wakeup = 1 ;
245+ }
246+ if (popWaiting_) {
247+ popWaiting_->fast_notify_all (lock);
248+ popWaiting_ = (ConditionVariable*)kClosedWaiting ;
249+ pop_wakeup = 1 ;
250+ }
251+
252+ RS_DBG (dbg_channel, " channel(...)=%ld | %s | no-cap branch | push-wakeup=%ld | pop-wakeup=%ld" ,
253+ id (), __func__, push_wakeup, pop_wakeup);
254+ }
255+
221256protected:
222257 Mutex mtx_;
223258 ConditionVariable pushCv_;
@@ -228,6 +263,8 @@ class ChannelImplWithSignal : public DebuggerId<ChannelImplWithSignal<int>>
228263 T* popQ_ {nullptr };
229264 ConditionVariable* pushWaiting_ {nullptr };
230265 ConditionVariable* popWaiting_ {nullptr };
266+
267+ static const std::size_t kClosedWaiting = (std::size_t )-1 ;
231268};
232269
233270template <
@@ -248,6 +285,7 @@ class ChannelImpl : public ChannelImplWithSignal<T>
248285 using ChannelImplWithSignal<T>::pop_impl_with_signal;
249286 using ChannelImplWithSignal<T>::push_impl_with_signal;
250287 using ChannelImplWithSignal<T>::id;
288+ using ChannelImplWithSignal<T>::impl_with_signal_close;
251289
252290 explicit ChannelImpl (std::size_t capacity = 0 )
253291 : cap_(capacity)
@@ -302,22 +340,16 @@ class ChannelImpl : public ChannelImplWithSignal<T>
302340 std::unique_lock<Mutex> lock (mtx_);
303341 closed_ = true ;
304342 if (!cap_) {
305- pushQ_ = nullptr ;
306- popQ_ = nullptr ;
307- if (pushWaiting_) {
308- pushWaiting_->fast_notify_all (lock);
309- pushWaiting_ = nullptr ;
310- }
311- if (popWaiting_) {
312- popWaiting_->fast_notify_all (lock);
313- popWaiting_ = nullptr ;
314- }
343+ impl_with_signal_close (lock);
315344 }
316345
317- pushCv_.fast_notify_all (lock);
318- popCv_.fast_notify_all (lock);
319- QueueT q;
320- std::swap (q, q_);
346+ long push_wakeup = pushCv_.fast_notify_all (lock);
347+ long pop_wakeup = popCv_.fast_notify_all (lock);
348+ (void )push_wakeup;
349+ (void )pop_wakeup;
350+
351+ RS_DBG (dbg_channel, " channel(queue)=%ld | %s | cap=%lu | size=%lu | push-wakeup=%ld | pop-wakeup=%ld" ,
352+ id (), __func__, cap_, q_.size (), push_wakeup, pop_wakeup);
321353 }
322354
323355private:
@@ -349,7 +381,7 @@ class ChannelImpl : public ChannelImplWithSignal<T>
349381 return false ;
350382 }
351383
352- auto p = [this ]{ return q_.size () < cap_; };
384+ auto p = [this ]{ return q_.size () < cap_ || closed_ ; };
353385
354386 RS_DBG (dbg_channel, " channel(queue)=%ld | %s | begin wait" ,
355387 id (), __func__);
@@ -404,7 +436,7 @@ class ChannelImpl : public ChannelImplWithSignal<T>
404436 return false ;
405437 }
406438
407- auto p = [this ]{ return !q_.empty (); };
439+ auto p = [this ]{ return !q_.empty () || closed_ ; };
408440
409441 RS_DBG (dbg_channel, " channel(queue)=%ld | %s | begin wait" ,
410442 id (), __func__);
@@ -418,7 +450,7 @@ class ChannelImpl : public ChannelImplWithSignal<T>
418450 if (status == std::cv_status::timeout)
419451 return false ;
420452
421- if (closed_ )
453+ if (q_. empty () )
422454 return false ;
423455
424456 t = q_.front ();
@@ -454,6 +486,7 @@ class ChannelImpl<nullptr_t, QueueT> : public ChannelImplWithSignal<nullptr_t>
454486 using ChannelImplWithSignal<nullptr_t >::pop_impl_with_signal;
455487 using ChannelImplWithSignal<nullptr_t >::push_impl_with_signal;
456488 using ChannelImplWithSignal<nullptr_t >::id;
489+ using ChannelImplWithSignal<nullptr_t >::impl_with_signal_close;
457490
458491 explicit ChannelImpl (std::size_t capacity = 0 )
459492 : cap_(capacity), count_(0 )
@@ -508,21 +541,16 @@ class ChannelImpl<nullptr_t, QueueT> : public ChannelImplWithSignal<nullptr_t>
508541 std::unique_lock<Mutex> lock (mtx_);
509542 closed_ = true ;
510543 if (!cap_) {
511- pushQ_ = nullptr ;
512- popQ_ = nullptr ;
513- if (pushWaiting_) {
514- pushWaiting_->fast_notify_all (lock);
515- pushWaiting_ = nullptr ;
516- }
517- if (popWaiting_) {
518- popWaiting_->fast_notify_all (lock);
519- popWaiting_ = nullptr ;
520- }
544+ impl_with_signal_close (lock);
521545 }
522546
523- pushCv_.fast_notify_all (lock);
524- popCv_.fast_notify_all (lock);
525- count_ = 0 ;
547+ long push_wakeup = pushCv_.fast_notify_all (lock);
548+ long pop_wakeup = popCv_.fast_notify_all (lock);
549+ (void )push_wakeup;
550+ (void )pop_wakeup;
551+
552+ RS_DBG (dbg_channel, " channel(void)=%ld | %s | cap=%lu | size=%lu | push-wakeup=%ld | pop-wakeup=%ld" ,
553+ id (), __func__, cap_, count_, push_wakeup, pop_wakeup);
526554 }
527555
528556private:
@@ -554,7 +582,7 @@ class ChannelImpl<nullptr_t, QueueT> : public ChannelImplWithSignal<nullptr_t>
554582 return false ;
555583 }
556584
557- auto p = [this ]{ return count_ < cap_; };
585+ auto p = [this ]{ return count_ < cap_ || closed_ ; };
558586
559587 RS_DBG (dbg_channel, " channel(void)=%ld | %s | begin wait" ,
560588 id (), __func__);
@@ -607,7 +635,7 @@ class ChannelImpl<nullptr_t, QueueT> : public ChannelImplWithSignal<nullptr_t>
607635 return false ;
608636 }
609637
610- auto p = [this ]{ return count_ > 0 ; };
638+ auto p = [this ]{ return count_ > 0 || closed_ ; };
611639
612640 RS_DBG (dbg_channel, " channel(void)=%ld | %s | begin wait" ,
613641 id (), __func__);
@@ -621,7 +649,7 @@ class ChannelImpl<nullptr_t, QueueT> : public ChannelImplWithSignal<nullptr_t>
621649 if (status == std::cv_status::timeout)
622650 return false ;
623651
624- if (closed_ )
652+ if (count_ <= 0 )
625653 return false ;
626654
627655 --count_;
0 commit comments