1 /* 2 * Copyright 2017 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkTaskGroup2D.h" 9 10 void SkTaskGroup2D::start() { 11 fThreadsGroup->batch(fThreadCnt, [this](int threadId){ 12 this->work(threadId); 13 }); 14 } 15 16 void SkTaskGroup2D::addColumn() { 17 SkASSERT(!fIsFinishing); // we're not supposed to add more work after the calling of finish 18 fWidth++; 19 } 20 21 void SkTaskGroup2D::finish() { 22 fIsFinishing.store(true, std::memory_order_relaxed); 23 fThreadsGroup->wait(); 24 } 25 26 void SkSpinningTaskGroup2D::work(int threadId) { 27 int& nextColumn = fRowData[threadId].fNextColumn; 28 29 while (true) { 30 SkASSERT(nextColumn <= fWidth); 31 if (this->isFinishing() && nextColumn >= fWidth) { 32 return; 33 } 34 35 if (nextColumn < fWidth) { 36 fWork(threadId, nextColumn); 37 nextColumn++; 38 } 39 } 40 } 41 42 SkFlexibleTaskGroup2D::SkFlexibleTaskGroup2D(Work2D&& w, int h, SkExecutor* x, int t) 43 : SkTaskGroup2D(std::move(w), h, x, t), fRowData(h), fThreadData(t) { 44 for (int i = 0; i < t; ++i) { 45 fThreadData[i].fRowIndex = i; 46 } 47 } 48 49 50 void SkFlexibleTaskGroup2D::work(int threadId) { 51 int failCnt = 0; 52 int& rowIndex = fThreadData[threadId].fRowIndex; 53 54 // This loop looks for work to do as long as 55 // either 1. isFinishing is false 56 // or 2. isFinishing is true but some rows still have unfinished tasks 57 while (true) { 58 RowData& rowData = fRowData[rowIndex]; 59 bool processed = false; 60 61 // The Android roller somehow gets a false-positive compile warning/error about the try-lock 62 // and unlock process. Hence we disable -Wthread-safety-analysis to bypass it. 63 #ifdef __clang__ 64 #pragma clang diagnostic push 65 #pragma clang diagnostic ignored "-Wthread-safety-analysis" 66 #endif 67 if (rowData.fMutex.try_lock()) { 68 if (rowData.fNextColumn < fWidth) { 69 fWork(rowIndex, rowData.fNextColumn); 70 rowData.fNextColumn++; 71 processed = true; 72 } else { 73 // isFinishing can never go from true to false. Once it's true, we count how many 74 // times that a row is out of work. If that count reaches fHeight, then we're out of 75 // work for the whole group. 76 failCnt += this->isFinishing(); 77 } 78 rowData.fMutex.unlock(); 79 } 80 #ifdef __clang__ 81 #pragma clang diagnostic pop 82 #endif 83 84 if (!processed) { 85 if (failCnt >= fHeight) { 86 return; 87 } 88 rowIndex = (rowIndex + 1) % fHeight; 89 } 90 } 91 } 92