| 669 | // ask about tasks. |
| 670 | |
| 671 | void WorkQueue::ThreadMain() { |
| 672 | int thread_id; |
| 673 | { |
| 674 | butil::AutoLock auto_lock(lock_); |
| 675 | thread_id = GetThreadId(); |
| 676 | if (EveryIdWasAllocated()) |
| 677 | all_threads_have_ids()->Signal(); // Tell creator we're ready. |
| 678 | } |
| 679 | |
| 680 | Lock private_lock; // Used to waste time on "our work". |
| 681 | while (1) { // This is the main consumer loop. |
| 682 | TimeDelta work_time; |
| 683 | bool could_use_help; |
| 684 | { |
| 685 | butil::AutoLock auto_lock(lock_); |
| 686 | while (0 == task_count() && !shutdown()) { |
| 687 | ++waiting_thread_count_; |
| 688 | work_is_available()->Wait(); |
| 689 | --waiting_thread_count_; |
| 690 | } |
| 691 | if (shutdown()) { |
| 692 | // Ack the notification of a shutdown message back to the controller. |
| 693 | thread_shutting_down(); |
| 694 | return; // Terminate. |
| 695 | } |
| 696 | // Get our task duration from the queue. |
| 697 | work_time = GetAnAssignment(thread_id); |
| 698 | could_use_help = (task_count() > 0) && allow_help_requests(); |
| 699 | } // Release lock |
| 700 | |
| 701 | // Do work (outside of locked region. |
| 702 | if (could_use_help) |
| 703 | work_is_available()->Signal(); // Get help from other threads. |
| 704 | |
| 705 | if (work_time > TimeDelta::FromMilliseconds(0)) { |
| 706 | // We could just sleep(), but we'll instead further exercise the |
| 707 | // condition variable class, and do a timed wait. |
| 708 | butil::AutoLock auto_lock(private_lock); |
| 709 | ConditionVariable private_cv(&private_lock); |
| 710 | private_cv.TimedWait(work_time); // Unsynchronized waiting. |
| 711 | } |
| 712 | |
| 713 | { |
| 714 | butil::AutoLock auto_lock(lock_); |
| 715 | // Send notification that we completed our "work." |
| 716 | WorkIsCompleted(thread_id); |
| 717 | } |
| 718 | } |
| 719 | } |
| 720 | |
| 721 | } // namespace |
| 722 | |