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)11SkTaskGroup::SkTaskGroup(SkExecutor& executor) : fPending(0), fExecutor(executor) {} 12 add(std::function<void (void)> fn)13void 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)21void 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()32void 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)42SkTaskGroup::Enabler::Enabler(int threads) { 43 if (threads) { 44 fThreadPool = SkExecutor::MakeThreadPool(threads); 45 SkExecutor::SetDefault(fThreadPool.get()); 46 } 47 } 48