/* * 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; } } }