single_thread_executor.h 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. // Copyright (c) Meta Platforms, Inc. and affiliates.
  2. //
  3. // This source code is licensed under both the GPLv2 (found in the
  4. // COPYING file in the root directory) and Apache 2.0 License
  5. // (found in the LICENSE.Apache file in the root directory).
  6. //
  7. #pragma once
  8. #if USE_COROUTINES
  9. #include <atomic>
  10. #include <queue>
  11. #include "folly/CPortability.h"
  12. #include "folly/CppAttributes.h"
  13. #include "folly/Executor.h"
  14. #include "util/async_file_reader.h"
  15. namespace ROCKSDB_NAMESPACE {
  16. // Implements a simple executor that runs callback functions in the same
  17. // thread, unlike CPUThreadExecutor which may schedule the callback on
  18. // another thread. Runs in a tight loop calling the queued callbacks,
  19. // and polls for async IO completions when idle. The completions will
  20. // resume suspended coroutines and they get added to the queue, which
  21. // will get picked up by this loop.
  22. // Any possibility of deadlock is precluded because the file system
  23. // guarantees that async IO completion callbacks will not be scheduled
  24. // to run in this thread or this executor.
  25. class SingleThreadExecutor : public folly::Executor {
  26. public:
  27. explicit SingleThreadExecutor(AsyncFileReader& reader)
  28. : reader_(reader), busy_(false) {}
  29. void add(folly::Func callback) override {
  30. auto& q = q_;
  31. q.push(std::move(callback));
  32. if (q.size() == 1 && !busy_) {
  33. while (!q.empty()) {
  34. q.front()();
  35. q.pop();
  36. if (q.empty()) {
  37. // Prevent recursion, as the Wait may queue resumed coroutines
  38. busy_ = true;
  39. reader_.Wait();
  40. busy_ = false;
  41. }
  42. }
  43. }
  44. }
  45. private:
  46. std::queue<folly::Func> q_;
  47. AsyncFileReader& reader_;
  48. bool busy_;
  49. };
  50. } // namespace ROCKSDB_NAMESPACE
  51. #endif // USE_COROUTINES