| 655 | } |
| 656 | |
| 657 | void cmWorkerPoolInternal::Work(unsigned int workerIndex) |
| 658 | { |
| 659 | cmWorkerPool::JobHandleT jobHandle; |
| 660 | std::unique_lock<std::mutex> uLock(this->Mutex); |
| 661 | // Increment running workers count |
| 662 | ++this->WorkersRunning; |
| 663 | // Enter worker main loop |
| 664 | while (true) { |
| 665 | // Abort on request |
| 666 | if (this->Aborting) { |
| 667 | break; |
| 668 | } |
| 669 | // Wait for new jobs on the main CV |
| 670 | if (this->Queue.empty()) { |
| 671 | ++this->WorkersIdle; |
| 672 | this->Condition.wait(uLock); |
| 673 | --this->WorkersIdle; |
| 674 | continue; |
| 675 | } |
| 676 | |
| 677 | // If there is a fence currently active or waiting, |
| 678 | // sleep on the main CV and try again. |
| 679 | if (this->FenceProcessing) { |
| 680 | this->Condition.wait(uLock); |
| 681 | continue; |
| 682 | } |
| 683 | |
| 684 | // Pop next job from queue |
| 685 | jobHandle = std::move(this->Queue.front()); |
| 686 | this->Queue.pop_front(); |
| 687 | |
| 688 | // Check for fence jobs |
| 689 | bool raisedFence = false; |
| 690 | if (jobHandle->IsFence()) { |
| 691 | this->FenceProcessing = true; |
| 692 | raisedFence = true; |
| 693 | // Wait on the Fence CV until all pending jobs are done. |
| 694 | while (this->JobsProcessing != 0 && !this->Aborting) { |
| 695 | this->ConditionFence.wait(uLock); |
| 696 | } |
| 697 | // When aborting, explicitly kick all threads alive once more. |
| 698 | if (this->Aborting) { |
| 699 | this->FenceProcessing = false; |
| 700 | this->Condition.notify_all(); |
| 701 | break; |
| 702 | } |
| 703 | } |
| 704 | |
| 705 | // Unlocked scope for job processing |
| 706 | ++this->JobsProcessing; |
| 707 | { |
| 708 | uLock.unlock(); |
| 709 | jobHandle->Work(this->Pool, workerIndex); // Process job |
| 710 | jobHandle.reset(); // Destroy job |
| 711 | uLock.lock(); |
| 712 | } |
| 713 | --this->JobsProcessing; |
| 714 | |