quill
ManualBackendWorker.h
1 
7 #pragma once
8 
9 #include "quill/backend/BackendOptions.h"
10 #include "quill/backend/BackendWorker.h"
11 #include <cassert>
12 #include <chrono>
13 #include <limits>
14 
15 QUILL_BEGIN_NAMESPACE
16 
21 {
22 public:
23  explicit ManualBackendWorker(detail::BackendWorker* backend_worker)
24  : _backend_worker(backend_worker)
25  {
26  }
27 
29  {
30  if (_started)
31  {
32  _backend_worker->_exit();
33  }
34  }
35 
44  void init(BackendOptions options)
45  {
46  options.sleep_duration = std::chrono::nanoseconds{0};
47  options.enable_yield_when_idle = false;
48  _backend_worker->_init(options);
49  _started = true;
50  }
51 
60  void poll_one()
61  {
62  assert((_backend_worker->_options.sleep_duration.count() == 0) &&
63  "call init() prior to calling this function");
64  assert((_backend_worker->_options.enable_yield_when_idle == false) &&
65  "call init() prior to calling this function");
66  assert((_backend_worker->_worker_thread_id.load() != 0) &&
67  "call init() prior to calling this function");
68  assert((_backend_worker->_worker_thread_id.load() == detail::get_thread_id()) &&
69  "poll() must be always called from the same thread");
70 
71  QUILL_TRY { _backend_worker->_poll(); }
72 #if !defined(QUILL_NO_EXCEPTIONS)
73  QUILL_CATCH(std::exception const& e) { _backend_worker->_options.error_notifier(e.what()); }
74  QUILL_CATCH_ALL()
75  {
76  _backend_worker->_options.error_notifier(std::string{"Caught unhandled exception."});
77  } // clang-format on
78 #endif
79  }
80 
86  void poll()
87  {
88  while (!_backend_worker->_check_frontend_queues_and_cached_transit_events_empty())
89  {
90  poll_one();
91  }
92  }
93 
98  void poll(std::chrono::microseconds timeout)
99  {
100  auto const start = std::chrono::steady_clock::now();
101  while (!_backend_worker->_check_frontend_queues_and_cached_transit_events_empty())
102  {
103  poll_one();
104 
105  auto const now = std::chrono::steady_clock::now();
106 
107  if ((now - start) > timeout)
108  {
109  break;
110  }
111  }
112  }
113 
114 private:
115  detail::BackendWorker* _backend_worker;
116  bool _started{false};
117 };
118 
119 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:98
std::function< void(std::string const &)> error_notifier
The backend may encounter exceptions that cannot be caught within user threads.
Definition: BackendOptions.h:162
void init(BackendOptions options)
Initializes the ManualBackendWorker with the specified backend options.
Definition: ManualBackendWorker.h:44
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:20
void poll()
Continuously polls the backend worker until all queues are empty.
Definition: ManualBackendWorker.h:86
void poll_one()
Polls all thread-local SPSC queues and caches the log statements, processing and writing the log stat...
Definition: ManualBackendWorker.h:60
Definition: BackendWorker.h:72
QUILL_NODISCARD QUILL_EXPORT QUILL_ATTRIBUTE_USED uint32_t get_thread_id() noexcept
Returns the os assigned ID of the thread.
Definition: ThreadUtilities.h:193
Configuration options for the backend.
Definition: BackendOptions.h:30