Commit 5d5bca6a394916c65d1fa386a5b0b44d4d20f76b
1 parent
8057fb57
Rearrange the release/reserve threads in stream::projectUpdate
In stream projectUpdate, queue the intial worker thread before calling releaseThread, and waiting. Also, call reserveThread before the last worker thread ends. The goal here is to avoid cases where the threadCount is increased, before the extra thread is used up by the current stream, as part of a scheme to avoid deadlocks related to using stream within an active distribute transform.
Showing
1 changed file
with
13 additions
and
5 deletions
openbr/plugins/stream.cpp
| ... | ... | @@ -226,6 +226,12 @@ public: |
| 226 | 226 | last_received = inputFrame->sequenceNumber; |
| 227 | 227 | |
| 228 | 228 | if (inputFrame->sequenceNumber == final_frame) { |
| 229 | + // This is the reserveThread that matches the releaseThread in | |
| 230 | + // Stream::projectUpdate, we do it here to prevent a gap where the | |
| 231 | + // thread count is still increased, but a stream worker thread is not | |
| 232 | + // running, which might allow something to start that shouldn't | |
| 233 | + // start yet. | |
| 234 | + QThreadPool::globalInstance()->reserveThread(); | |
| 229 | 235 | // We just received the last frame, better pulse |
| 230 | 236 | lastReturned.wakeAll(); |
| 231 | 237 | rval = true; |
| ... | ... | @@ -630,7 +636,7 @@ public: |
| 630 | 636 | next->start_idx = this->stage_id; |
| 631 | 637 | next->startItem = newItem; |
| 632 | 638 | |
| 633 | - QThreadPool::globalInstance()->start(next, stages->size() - this->stage_id); | |
| 639 | + QThreadPool::globalInstance()->start(next, stages->size() - stage_id); | |
| 634 | 640 | } |
| 635 | 641 | |
| 636 | 642 | return input; |
| ... | ... | @@ -700,7 +706,7 @@ public: |
| 700 | 706 | next->start_idx = this->stage_id; |
| 701 | 707 | next->startItem = NULL; |
| 702 | 708 | |
| 703 | - QThreadPool::globalInstance()->start(next, stages->size() - this->stage_id); | |
| 709 | + QThreadPool::globalInstance()->start(next, stages->size() - stage_id); | |
| 704 | 710 | |
| 705 | 711 | return input; |
| 706 | 712 | } |
| ... | ... | @@ -791,7 +797,7 @@ public: |
| 791 | 797 | next->start_idx = this->stage_id; |
| 792 | 798 | next->startItem = newItem; |
| 793 | 799 | |
| 794 | - QThreadPool::globalInstance()->start(next, stages->size() - this->stage_id); | |
| 800 | + QThreadPool::globalInstance()->start(next, stages->size() - stage_id); | |
| 795 | 801 | } |
| 796 | 802 | |
| 797 | 803 | return input; |
| ... | ... | @@ -831,7 +837,6 @@ public: |
| 831 | 837 | bool res = readStage->dataSource.open(dst); |
| 832 | 838 | if (!res) return; |
| 833 | 839 | |
| 834 | - QThreadPool::globalInstance()->releaseThread(); | |
| 835 | 840 | readStage->currentStatus = SingleThreadStage::STARTING; |
| 836 | 841 | |
| 837 | 842 | BasicLoop loop; |
| ... | ... | @@ -840,11 +845,14 @@ public: |
| 840 | 845 | loop.startItem = NULL; |
| 841 | 846 | loop.setAutoDelete(false); |
| 842 | 847 | |
| 848 | + // Create a thread, then allow it to start by releasing. We queue the thread | |
| 849 | + // first so that any lower priority threads that are already queued don't start | |
| 850 | + // instead of the new one. | |
| 843 | 851 | QThreadPool::globalInstance()->start(&loop, processingStages.size() - processingStages[0]->stage_id); |
| 852 | + QThreadPool::globalInstance()->releaseThread(); | |
| 844 | 853 | |
| 845 | 854 | // Wait for the end. |
| 846 | 855 | readStage->dataSource.waitLast(); |
| 847 | - QThreadPool::globalInstance()->reserveThread(); | |
| 848 | 856 | |
| 849 | 857 | TemplateList final_output; |
| 850 | 858 | ... | ... |