@@ -287,16 +287,21 @@ void AsyncPipe::Impl::appendLockless(const void *data_ptr, size_t data_size)
287
287
288
288
void AsyncPipe::Impl::threadFunc ()
289
289
{
290
- do {
291
- bool is_wake_for_timeup = true ; // ! 是否因超时而唤醒
290
+ for (;;) {
291
+ bool is_wake_for_quit = false ; // ! 是否因需要停止而被唤醒
292
+ bool is_wake_for_timeup = true ; // ! 是否因超时而被唤醒
293
+
292
294
{
293
295
// ! 等待唤醒信号
294
296
std::unique_lock<std::mutex> lk (full_buffers_mutex_);
295
297
if (full_buffers_.empty ()) {
296
298
// ! 等待三种情况: 1.超时,2.停止,3.full_buffers_不为空
297
299
full_buffers_cv_.wait_for (lk, std::chrono::milliseconds (cfg_.interval ),
298
- [&is_wake_for_timeup, this ] {
299
- if (stop_signal_ || !full_buffers_.empty ()) {
300
+ [this , &is_wake_for_timeup, &is_wake_for_quit] {
301
+ if (stop_signal_)
302
+ is_wake_for_quit = true ;
303
+
304
+ if (is_wake_for_quit || !full_buffers_.empty ()) {
300
305
is_wake_for_timeup = false ;
301
306
return true ;
302
307
}
@@ -307,7 +312,22 @@ void AsyncPipe::Impl::threadFunc()
307
312
is_wake_for_timeup = false ;
308
313
}
309
314
}
310
- // ! 先处理 full_buffers_ 中的数据
315
+
316
+ // ! 如果是超时或是收到停止信号,则先将 curr_buff_ 移到 full_buffers_
317
+ if (is_wake_for_timeup || is_wake_for_quit) {
318
+ if (curr_buffer_mutex_.try_lock ()) {
319
+ if (curr_buffer_ != nullptr ) {
320
+ // ! Q: 这里为什么不锁 full_buffers_mutex_ ?
321
+ // ! A: 因为锁住了 curr_buffer_mutex_ 就不会有前端调用 appendLockless(),仅有后端的线程操作。
322
+ // ! 所以不锁 full_buffers_mutex_ 也是安全的
323
+ full_buffers_.push_back (curr_buffer_);
324
+ curr_buffer_ = nullptr ;
325
+ }
326
+ curr_buffer_mutex_.unlock ();
327
+ }
328
+ }
329
+
330
+ // ! 然后逐一处理 full_buffers_ 中的数据
311
331
for (;;) {
312
332
Buffer *buff = nullptr ;
313
333
{
@@ -316,8 +336,9 @@ void AsyncPipe::Impl::threadFunc()
316
336
if (!full_buffers_.empty ()) {
317
337
buff = full_buffers_.front ();
318
338
full_buffers_.pop_front ();
319
- } else
339
+ } else {
320
340
break ;
341
+ }
321
342
}
322
343
323
344
if (buff != nullptr ) {
@@ -341,32 +362,9 @@ void AsyncPipe::Impl::threadFunc()
341
362
}
342
363
}
343
364
344
- // ! 如果是超时或是收到停止信号,则检查并处理 curr_buffer_ 中的数据
345
- if (is_wake_for_timeup || stop_signal_) {
346
- Buffer *buff = nullptr ;
347
- if (curr_buffer_mutex_.try_lock ()) {
348
- // ! 注意:这里一定要用 try_lock(),否则会死锁
349
- if (curr_buffer_ != nullptr && !curr_buffer_->empty ()) {
350
- buff = curr_buffer_;
351
- curr_buffer_ = nullptr ;
352
- }
353
- curr_buffer_mutex_.unlock ();
354
- }
355
-
356
- if (buff != nullptr ) { // ! 如果没取出来
357
- // ! 进行处理
358
- if (cb_)
359
- cb_ (buff->data (), buff->size ());
360
- buff->reset ();
361
- // ! 然后将处理后的buff放入到free_buffers_中
362
- std::lock_guard<std::mutex> lg (free_buffers_mutex_);
363
- free_buffers_.push_back (buff);
364
- free_buffers_cv_.notify_all ();
365
- }
366
- }
367
- } while (!stop_signal_); // ! 如果是停止信号,则直接跳出循环,结束线程
368
- // ! Q: stop_signal_ 信号为什么不在被唤醒时就break呢?
369
- // ! A: 因为我们期望就算是退出了,Buff中的数据都应该先被处理掉
365
+ if (is_wake_for_quit)
366
+ break ;
367
+ }
370
368
}
371
369
372
370
}
0 commit comments