Home | History | Annotate | Download | only in core
      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 SkTaskGroup::SkTaskGroup(SkExecutor& executor) : fPending(0), fExecutor(executor) {}
     12 
     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 
     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 
     32 bool SkTaskGroup::done() const {
     33     return fPending.load(std::memory_order_acquire) == 0;
     34 }
     35 
     36 void SkTaskGroup::wait() {
     37     // Actively help the executor do work until our task group is done.
     38     // This lets SkTaskGroups nest arbitrarily deep on a single SkExecutor:
     39     // no thread ever blocks waiting for others to do its work.
     40     // (We may end up doing work that's not part of our task group.  That's fine.)
     41     while (!this->done()) {
     42         fExecutor.borrow();
     43     }
     44 }
     45 
     46 SkTaskGroup::Enabler::Enabler(int threads) {
     47     if (threads) {
     48         fThreadPool = SkExecutor::MakeLIFOThreadPool(threads);
     49         SkExecutor::SetDefault(fThreadPool.get());
     50     }
     51 }
     52