Skip to content

Commit f4a3d15

Browse files
author
yuyangzi
committed
channel.close时不再清空缓存, 以便于还可以继续读
1 parent 093285d commit f4a3d15

2 files changed

Lines changed: 334 additions & 59 deletions

File tree

libgo/routine_sync/channel.h

Lines changed: 84 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
221256
protected:
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

233270
template <
@@ -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

323355
private:
@@ -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

528556
private:
@@ -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

Comments
 (0)