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 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 
     42 SkTaskGroup::Enabler::Enabler(int threads) {
     43     if (threads) {
     44         fThreadPool = SkExecutor::MakeThreadPool(threads);
     45         SkExecutor::SetDefault(fThreadPool.get());
     46     }
     47 }
     48