Line data Source code
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 :
11 0 : SkTaskGroup::SkTaskGroup(SkExecutor& executor) : fPending(0), fExecutor(executor) {}
12 :
13 0 : void SkTaskGroup::add(std::function<void(void)> fn) {
14 0 : fPending.fetch_add(+1, std::memory_order_relaxed);
15 0 : fExecutor.add([=] {
16 0 : fn();
17 0 : fPending.fetch_add(-1, std::memory_order_release);
18 0 : });
19 0 : }
20 :
21 0 : 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 0 : fPending.fetch_add(+N, std::memory_order_relaxed);
24 0 : for (int i = 0; i < N; i++) {
25 0 : fExecutor.add([=] {
26 0 : fn(i);
27 0 : fPending.fetch_add(-1, std::memory_order_release);
28 0 : });
29 : }
30 0 : }
31 :
32 0 : 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 0 : while (fPending.load(std::memory_order_acquire) > 0) {
38 0 : fExecutor.borrow();
39 : }
40 0 : }
41 :
42 0 : SkTaskGroup::Enabler::Enabler(int threads) {
43 0 : if (threads) {
44 0 : fThreadPool = SkExecutor::MakeThreadPool(threads);
45 0 : SkExecutor::SetDefault(fThreadPool.get());
46 : }
47 0 : }
|