diff options
Diffstat (limited to 'src/core/SkTaskGroup2D.cpp')
-rw-r--r-- | src/core/SkTaskGroup2D.cpp | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/src/core/SkTaskGroup2D.cpp b/src/core/SkTaskGroup2D.cpp new file mode 100644 index 0000000000..fe8a5a89be --- /dev/null +++ b/src/core/SkTaskGroup2D.cpp @@ -0,0 +1,91 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkTaskGroup2D.h" + +void SkTaskGroup2D::start() { + fThreadsGroup->batch(fThreadCnt, [this](int threadId){ + this->work(threadId); + }); +} + +void SkTaskGroup2D::addColumn() { + SkASSERT(!fIsFinishing); // we're not supposed to add more work after the calling of finish + fWidth++; +} + +void SkTaskGroup2D::finish() { + fIsFinishing.store(true, std::memory_order_relaxed); + fThreadsGroup->wait(); +} + +void SkSpinningTaskGroup2D::work(int threadId) { + int& nextColumn = fRowData[threadId].fNextColumn; + + while (true) { + SkASSERT(nextColumn <= fWidth); + if (this->isFinishing() && nextColumn >= fWidth) { + return; + } + + if (nextColumn < fWidth) { + fWork(threadId, nextColumn); + nextColumn++; + } + } +} + +SkFlexibleTaskGroup2D::SkFlexibleTaskGroup2D(Work2D&& w, int h, SkExecutor* x, int t) + : SkTaskGroup2D(std::move(w), h, x, t), fRowData(h), fThreadData(t) { + for (int i = 0; i < t; ++i) { + fThreadData[i].fRowIndex = i; + } +} + + +void SkFlexibleTaskGroup2D::work(int threadId) { + int failCnt = 0; + int& rowIndex = fThreadData[threadId].fRowIndex; + + // This loop looks for work to do as long as + // either 1. isFinishing is false + // or 2. isFinishing is true but some rows still have unfinished tasks + while (true) { + RowData& rowData = fRowData[rowIndex]; + bool processed = false; + + // The Android roller somehow gets a false-positive compile warning/error about the try-lock + // and unlock process. Hence we disable -Wthread-safety-analysis to bypass it. +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wthread-safety-analysis" +#endif + if (rowData.fMutex.try_lock()) { + if (rowData.fNextColumn < fWidth) { + fWork(rowIndex, rowData.fNextColumn); + rowData.fNextColumn++; + processed = true; + } else { + // isFinishing can never go from true to false. Once it's true, we count how many + // times that a row is out of work. If that count reaches fHeight, then we're out of + // work for the whole group. + failCnt += this->isFinishing(); + } + rowData.fMutex.unlock(); + } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + + if (!processed) { + if (failCnt >= fHeight) { + return; + } + rowIndex = (rowIndex + 1) % fHeight; + } + } +} |