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 
20 {
21 public:
22  explicit ManualBackendWorker(detail::BackendWorker* backend_worker)
23  : _backend_worker(backend_worker)
24  {
25  }
26 
28  {
29  if (_started)
30  {
31  _backend_worker->_exit();
32  }
33  }
34 
43  void init(BackendOptions options)
44  {
45  options.sleep_duration = std::chrono::nanoseconds{0};
46  options.enable_yield_when_idle = false;
47  _backend_worker->_init(options);
48  _started = true;
49  }
50 
59  void poll_one()
60  {
61  QUILL_ASSERT(
62  _backend_worker->_options.sleep_duration.count() == 0,
63  "ManualBackendWorker::poll_one() requires init() to be called first with sleep_duration = 0");
64  QUILL_ASSERT(_backend_worker->_options.enable_yield_when_idle == false,
65  "ManualBackendWorker::poll_one() requires init() to be called first with "
66  "enable_yield_when_idle = false");
67  QUILL_ASSERT(_backend_worker->_worker_thread_id.load() != 0,
68  "ManualBackendWorker::poll_one() requires init() to be called first");
69  QUILL_ASSERT(_backend_worker->_worker_thread_id.load() == detail::get_thread_id(),
70  "ManualBackendWorker::poll_one() must always be called from the same thread");
71 
72  QUILL_TRY { _backend_worker->_poll(); }
73 #if !defined(QUILL_NO_EXCEPTIONS)
74  QUILL_CATCH(std::exception const& e) { _backend_worker->_options.error_notifier(e.what()); }
75  QUILL_CATCH_ALL()
76  {
77  _backend_worker->_options.error_notifier(std::string{"Caught unhandled exception."});
78  }
79 #endif
80  }
81 
87  void poll()
88  {
89  while (!_backend_worker->_check_frontend_queues_and_cached_transit_events_empty())
90  {
91  poll_one();
92  }
93  }
94 
99  void poll(std::chrono::microseconds timeout)
100  {
101  auto const start = std::chrono::steady_clock::now();
102  while (!_backend_worker->_check_frontend_queues_and_cached_transit_events_empty())
103  {
104  poll_one();
105 
106  auto const now = std::chrono::steady_clock::now();
107 
108  if ((now - start) > timeout)
109  {
110  break;
111  }
112  }
113  }
114 
115 private:
116  detail::BackendWorker* _backend_worker;
117  bool _started{false};
118 };
119 
120 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:44
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:99
std::function< void(std::string const &)> error_notifier
The backend may encounter exceptions that cannot be caught within user threads.
Definition: BackendOptions.h:170
void init(BackendOptions options)
Initializes the ManualBackendWorker with the specified backend options.
Definition: ManualBackendWorker.h:43
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:49
This class can be used when you want to run the backend worker on your own thread.
Definition: ManualBackendWorker.h:19
void poll()
Continuously polls the backend worker until all queues are empty.
Definition: ManualBackendWorker.h:87
void poll_one()
Polls all thread-local SPSC queues and caches the log statements, processing and writing the log stat...
Definition: ManualBackendWorker.h:59
Definition: BackendWorker.h:77
QUILL_NODISCARD QUILL_EXPORT QUILL_ATTRIBUTE_USED uint32_t get_thread_id() noexcept
Returns the os assigned ID of the thread.
Definition: ThreadUtilities.h:198
Configuration options for the backend.
Definition: BackendOptions.h:30