WaitCounter.h 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #pragma once
  2. #include <chrono>
  3. #include <memory>
  4. #include <string_view>
  5. #include <vector>
  6. #include <c10/macros/Macros.h>
  7. #include <c10/util/ScopeExit.h>
  8. #include <c10/util/SmallVector.h>
  9. namespace c10::monitor {
  10. namespace detail {
  11. class WaitCounterImpl;
  12. class WaitCounterBackendIf {
  13. public:
  14. virtual ~WaitCounterBackendIf() = default;
  15. virtual intptr_t start(
  16. std::chrono::steady_clock::time_point now) noexcept = 0;
  17. virtual void stop(
  18. std::chrono::steady_clock::time_point now,
  19. intptr_t ctx) noexcept = 0;
  20. };
  21. class WaitCounterBackendFactoryIf {
  22. public:
  23. virtual ~WaitCounterBackendFactoryIf() = default;
  24. // May return nullptr.
  25. // In this case the counter will be ignored by the given backend.
  26. virtual std::unique_ptr<WaitCounterBackendIf> create(
  27. std::string_view key) noexcept = 0;
  28. };
  29. C10_API void registerWaitCounterBackend(
  30. std::unique_ptr<WaitCounterBackendFactoryIf>);
  31. C10_API std::vector<std::shared_ptr<WaitCounterBackendFactoryIf>>
  32. getRegisteredWaitCounterBackends();
  33. } // namespace detail
  34. // A handle to a wait counter.
  35. class C10_API WaitCounterHandle {
  36. public:
  37. explicit WaitCounterHandle(std::string_view key);
  38. class WaitGuard {
  39. public:
  40. WaitGuard(WaitGuard&& other) noexcept
  41. : handle_{std::exchange(other.handle_, {})},
  42. ctxs_{std::move(other.ctxs_)} {}
  43. WaitGuard(const WaitGuard&) = delete;
  44. WaitGuard& operator=(const WaitGuard&) = delete;
  45. WaitGuard& operator=(WaitGuard&&) = delete;
  46. ~WaitGuard() {
  47. stop();
  48. }
  49. void stop() {
  50. if (auto handle = std::exchange(handle_, nullptr)) {
  51. handle->stop(ctxs_);
  52. }
  53. }
  54. private:
  55. WaitGuard(WaitCounterHandle& handle, SmallVector<intptr_t>&& ctxs)
  56. : handle_{&handle}, ctxs_{std::move(ctxs)} {}
  57. friend class WaitCounterHandle;
  58. WaitCounterHandle* handle_;
  59. SmallVector<intptr_t> ctxs_;
  60. };
  61. // Starts a waiter
  62. WaitGuard start();
  63. private:
  64. // Stops the waiter. Each start() call should be matched by exactly one stop()
  65. // call.
  66. void stop(const SmallVector<intptr_t>& ctxs);
  67. // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
  68. detail::WaitCounterImpl& impl_;
  69. };
  70. } // namespace c10::monitor
  71. #define STATIC_WAIT_COUNTER(_key) \
  72. []() -> ::c10::monitor::WaitCounterHandle& { \
  73. static ::c10::monitor::WaitCounterHandle handle(#_key); \
  74. return handle; \
  75. }()
  76. #define STATIC_SCOPED_WAIT_COUNTER(_name) \
  77. auto C10_ANONYMOUS_VARIABLE(SCOPE_GUARD) = STATIC_WAIT_COUNTER(_name).start();