• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 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 "SkExecutor.h"
9 #include "SkTaskGroup.h"
10 
SkTaskGroup(SkExecutor & executor)11 SkTaskGroup::SkTaskGroup(SkExecutor& executor) : fPending(0), fExecutor(executor) {}
12 
add(std::function<void (void)> fn)13 void SkTaskGroup::add(std::function<void(void)> fn) {
14     fPending.fetch_add(+1, std::memory_order_relaxed);
15     fExecutor.add([=] {
16         fn();
17         fPending.fetch_add(-1, std::memory_order_release);
18     });
19 }
20 
batch(int N,std::function<void (int)> fn)21 void SkTaskGroup::batch(int N, std::function<void(int)> fn) {
22     // TODO: I really thought we had some sort of more clever chunking logic.
23     fPending.fetch_add(+N, std::memory_order_relaxed);
24     for (int i = 0; i < N; i++) {
25         fExecutor.add([=] {
26             fn(i);
27             fPending.fetch_add(-1, std::memory_order_release);
28         });
29     }
30 }
31 
wait()32 void SkTaskGroup::wait() {
33     // Actively help the executor do work until our task group is done.
34     // This lets SkTaskGroups nest arbitrarily deep on a single SkExecutor:
35     // no thread ever blocks waiting for others to do its work.
36     // (We may end up doing work that's not part of our task group.  That's fine.)
37     while (fPending.load(std::memory_order_acquire) > 0) {
38         fExecutor.borrow();
39     }
40 }
41 
Enabler(int threads)42 SkTaskGroup::Enabler::Enabler(int threads) {
43     if (threads) {
44         fThreadPool = SkExecutor::MakeThreadPool(threads);
45         SkExecutor::SetDefault(fThreadPool.get());
46     }
47 }
48