aboutsummaryrefslogtreecommitdiff
path: root/src/core/SkTaskGroup2D.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/SkTaskGroup2D.cpp')
-rw-r--r--src/core/SkTaskGroup2D.cpp91
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;
+ }
+ }
+}