SkTaskGroup.cpp 1.5 KB

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