quill
ManualBackendWorker.h
1 
7 #pragma once
8 
9 #include "quill/backend/BackendOptions.h"
10 #include "quill/backend/BackendWorker.h"
11 #include <chrono>
12 #include <limits>
13 
14 QUILL_BEGIN_NAMESPACE
15 
16 QUILL_BEGIN_EXPORT
17 
31 {
32 public:
33  explicit ManualBackendWorker(detail::BackendWorker* backend_worker)
34  : _backend_worker(backend_worker)
35  {
36  }
37 
39  ManualBackendWorker& operator=(ManualBackendWorker const&) = delete;
41  ManualBackendWorker& operator=(ManualBackendWorker&&) = delete;
42 
44  {
45  // Preserve legacy behavior for callers that forgot explicit shutdown().
46  shutdown();
47  }
48 
57  void init(BackendOptions options)
58  {
59  QUILL_ASSERT(!_started, "ManualBackendWorker::init() must not be called more than once");
60 
61  options.sleep_duration = std::chrono::nanoseconds{0};
62  options.enable_yield_when_idle = false;
63  _backend_worker->_init(options);
64  _started = true;
65  }
66 
75  void shutdown()
76  {
77  if (!_started)
78  {
79  return;
80  }
81 
82  QUILL_ASSERT(_backend_worker->_worker_thread_id.load() == detail::get_thread_id(),
83  "ManualBackendWorker::shutdown() must be called from the same thread that "
84  "called init()");
85 
86  _backend_worker->_exit();
87  _backend_worker->_worker_thread_id.store(0);
88  _started = false;
89  }
90 
99  void poll_one()
100  {
101  QUILL_ASSERT(
102  _backend_worker->_options.sleep_duration.count() == 0,
103  "ManualBackendWorker::poll_one() requires init() to be called first with sleep_duration = 0");
104  QUILL_ASSERT(_backend_worker->_options.enable_yield_when_idle == false,
105  "ManualBackendWorker::poll_one() requires init() to be called first with "
106  "enable_yield_when_idle = false");
107  QUILL_ASSERT(_backend_worker->_worker_thread_id.load() != 0,
108  "ManualBackendWorker::poll_one() requires init() to be called first");
109  QUILL_ASSERT(_backend_worker->_worker_thread_id.load() == detail::get_thread_id(),
110  "ManualBackendWorker::poll_one() must always be called from the same thread");
111 
112  QUILL_TRY { _backend_worker->_poll(); }
113 #if !defined(QUILL_NO_EXCEPTIONS)
114  QUILL_CATCH(std::exception const& e)
115  {
116  detail::BackendWorker::_notify_error(_backend_worker->_options.error_notifier, e.what());
117  }
118  QUILL_CATCH_ALL()
119  {
120  detail::BackendWorker::_notify_error(_backend_worker->_options.error_notifier,
121  std::string{"Caught unhandled exception."});
122  }
123 #endif
124  }
125 
131  void poll()
132  {
133  while (!_backend_worker->_check_frontend_queues_and_cached_transit_events_empty())
134  {
135  poll_one();
136  }
137  }
138 
143  void poll(std::chrono::microseconds timeout)
144  {
145  auto const start = std::chrono::steady_clock::now();
146  while (!_backend_worker->_check_frontend_queues_and_cached_transit_events_empty())
147  {
148  poll_one();
149 
150  auto const now = std::chrono::steady_clock::now();
151 
152  if ((now - start) > timeout)
153  {
154  break;
155  }
156  }
157  }
158 
159 private:
160  detail::BackendWorker* _backend_worker;
161  bool _started{false};
162 };
163 
164 QUILL_END_EXPORT
165 
166 QUILL_END_NAMESPACE
bool enable_yield_when_idle
The backend employs "busy-waiting" by spinning around each frontend thread&#39;s queue.
Definition: BackendOptions.h:67
void poll(std::chrono::microseconds timeout)
This function behaves like poll() but will stop polling if the specified timeout duration is reached ...
Definition: ManualBackendWorker.h:143
std::function< void(std::string const &)> error_notifier
The backend may encounter exceptions that cannot be caught within user threads.
Definition: BackendOptions.h:241
void init(BackendOptions options)
Initializes the ManualBackendWorker with the specified backend options.
Definition: ManualBackendWorker.h:57
std::chrono::nanoseconds sleep_duration
Specifies the duration the backend sleeps if there is no remaining work to process in the queues...
Definition: BackendOptions.h:72
void shutdown()
Flushes remaining frontend queues and marks the manual backend worker as stopped. ...
Definition: ManualBackendWorker.h:75
This class can be used when you want to run the backend worker on your own thread.
Definition: ManualBackendWorker.h:30
void poll()
Continuously polls the backend worker until all queues are empty.
Definition: ManualBackendWorker.h:131
void poll_one()
Polls all thread-local SPSC queues and caches the log statements, processing and writing the log stat...
Definition: ManualBackendWorker.h:99
Definition: BackendWorker.h:80
QUILL_NODISCARD QUILL_EXPORT QUILL_ATTRIBUTE_USED uint32_t get_thread_id() noexcept
Returns the os assigned ID of the thread.
Definition: ThreadUtilities.h:213
Configuration options for the backend.
Definition: BackendOptions.h:51