• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
start()10 void SkTaskGroup2D::start() {
11     fThreadsGroup->batch(fThreadCnt, [this](int threadId){
12         this->work(threadId);
13     });
14 }
15 
addColumn()16 void SkTaskGroup2D::addColumn() {
17     SkASSERT(!fIsFinishing); // we're not supposed to add more work after the calling of finish
18     fWidth++;
19 }
20 
finish()21 void SkTaskGroup2D::finish() {
22     fIsFinishing.store(true, std::memory_order_relaxed);
23     fThreadsGroup->wait();
24 }
25 
work(int threadId)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 
SkFlexibleTaskGroup2D(Work2D && w,int h,SkExecutor * x,int t)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 
work(int threadId)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