coro_waker.h 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. //
  2. // Copyright (c) 2021-2026, Manticore Software LTD (https://manticoresearch.com)
  3. // All rights reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License. You should have
  7. // received a copy of the GPL license along with this program; if you
  8. // did not, you can find it at http://www.gnu.org
  9. //
  10. #pragma once
  11. #include "std/spinlock.h"
  12. #include <boost/intrusive/slist.hpp>
  13. namespace Threads
  14. {
  15. namespace Coro
  16. {
  17. class Worker_c;
  18. namespace detail
  19. {
  20. using waker_queue_hook_t = boost::intrusive::slist_member_hook<> ;
  21. }
  22. class Waker_c
  23. {
  24. Worker_c* m_pCtx {};
  25. size_t m_iEpoch {};
  26. friend class AtomicWaker_c;
  27. public:
  28. Waker_c() = default;
  29. Waker_c ( Worker_c* pCtx, const size_t iEpoch )
  30. : m_pCtx { pCtx }
  31. , m_iEpoch { iEpoch }
  32. {}
  33. bool Wake ( bool bVip = false ) const noexcept;
  34. };
  35. class AtomicWaker_c
  36. {
  37. std::atomic<Worker_c*> m_pCtx {nullptr};
  38. size_t m_iEpoch {};
  39. public:
  40. AtomicWaker_c() = default;
  41. void Assign ( Waker_c&& tWaker )
  42. {
  43. m_iEpoch = tWaker.m_iEpoch;
  44. m_pCtx.store ( tWaker.m_pCtx, std::memory_order_relaxed );
  45. }
  46. bool WakeOnce ( bool bVip = false ) noexcept;
  47. };
  48. class WakerInQueue_c: public Waker_c
  49. {
  50. public:
  51. explicit WakerInQueue_c ( Waker_c&& w )
  52. : Waker_c { w }
  53. {}
  54. bool is_linked() const noexcept
  55. {
  56. return m_tWakerQueueHook.is_linked();
  57. }
  58. friend bool operator== ( Waker_c const& lhs, Waker_c const& rhs ) noexcept
  59. {
  60. return &lhs == &rhs;
  61. }
  62. public:
  63. detail::waker_queue_hook_t m_tWakerQueueHook {};
  64. };
  65. namespace detail
  66. {
  67. using WakerSlist_t = boost::intrusive::slist<
  68. WakerInQueue_c,
  69. boost::intrusive::member_hook<
  70. WakerInQueue_c,
  71. detail::waker_queue_hook_t,
  72. &WakerInQueue_c::m_tWakerQueueHook>,
  73. boost::intrusive::constant_time_size<false>,
  74. boost::intrusive::cache_last<true>>;
  75. }
  76. class WaitQueue_c
  77. {
  78. private:
  79. detail::WakerSlist_t m_Slist {};
  80. public:
  81. void SuspendAndWait ( sph::Spinlock_lock& l, Worker_c* ) REQUIRES (l);
  82. bool SuspendAndWaitUntil ( sph::Spinlock_lock& l, Worker_c*, int64_t ) REQUIRES (l);
  83. bool SuspendAndWaitForMS ( sph::Spinlock_lock& l, Worker_c*, int64_t ) REQUIRES (l);
  84. void NotifyOne();
  85. void NotifyAll();
  86. bool Empty() const;
  87. };
  88. } // namespace Coro
  89. } // namespace Threads