41#ifndef _DWMLOADBALANCER_HH_
42#define _DWMLOADBALANCER_HH_
73 template <
typename ItemT>
88 Worker(std::chrono::microseconds waitNotEmptyMicroseconds = std::chrono::microseconds(1000))
89 : _workQueue(), _keepRunning(false), _thread(),
90 _waitUsecs(waitNotEmptyMicroseconds)
115 template <
typename InputIterator>
116 bool AddWork(InputIterator firstIter, InputIterator lastIter)
118 return (_workQueue.
PushBack(firstIter, lastIter) > 0);
126 return _workQueue.
Length();
148 || ((_workQueue.
Length() + numEntries)
177 _keepRunning =
false;
178 if (_thread.joinable()) {
189 return (_thread.joinable());
197 while (_keepRunning || (_workQueue.
Length())) {
199 std::deque<ItemT> myCopy;
200 _workQueue.
Swap(myCopy);
204 for (
auto i : myCopy) {
241 std::atomic<bool> _keepRunning;
243 std::atomic<std::chrono::microseconds> _waitUsecs;
253 std::lock_guard<std::mutex> lock(_mtx);
254 _workers.push_back(std::unique_ptr<Worker>(worker));
264 bool workAdded =
false;
266 std::lock_guard<std::mutex> lock(_mtx);
267 if (_workers.empty()) {
272 while (! workAdded) {
275 std::lock_guard<std::mutex> lock(_mtx);
276 auto w = std::min_element(_workers.begin(), _workers.end(),
277 [&] (
const std::unique_ptr<Worker> & a,
278 const std::unique_ptr<Worker> & b)
279 { return (a->QueueLength()
280 < b->QueueLength()); });
281 if (w != _workers.end()) {
282 workAdded = (*w)->AddWork(item);
286 std::this_thread::sleep_for(MinimumWaitForWorkerReady());
295 template <
typename InputIterator>
296 bool AddWork(InputIterator firstIter, InputIterator lastIter)
298 bool workAdded =
false;
300 std::lock_guard<std::mutex> lock(_mtx);
301 if (_workers.empty()) {
306 while (! WorkerReady(lastIter - firstIter)) {
307 std::this_thread::sleep_for(std::chrono::microseconds(MinimumWaitForWorkerReady()));
310 std::lock_guard<std::mutex> lock(_mtx);
311 auto w = std::min_element(_workers.begin(), _workers.end(),
312 [&] (
const std::unique_ptr<Worker> & a,
313 const std::unique_ptr<Worker> & b)
314 { return (a->QueueLength() < b->QueueLength()); });
315 return (*w)->AddWork(firstIter, lastIter);
323 std::lock_guard<std::mutex> lock(_mtx);
324 for (
auto & w : _workers) {
334 const std::vector<std::unique_ptr<Worker>> &
Workers()
const
340 mutable std::mutex _mtx;
341 std::vector<std::unique_ptr<Worker>> _workers;
349 std::lock_guard<std::mutex> lock(_mtx);
350 for (
auto & w : _workers) {
351 if (w->ReadyForWork()) {
363 bool WorkerReady(
size_t numEntries)
const
366 std::lock_guard<std::mutex> lock(_mtx);
367 for (
auto & w : _workers) {
368 if (w->ReadyForWork(numEntries)) {
379 std::chrono::microseconds MinimumWaitForWorkerReady()
const
381 std::chrono::microseconds rc(1000);
382 std::lock_guard<std::mutex> lock(_mtx);
383 auto w = std::min_element(_workers.begin(), _workers.end(),
384 [&] (
const std::unique_ptr<Worker> & a,
385 const std::unique_ptr<Worker> & b)
386 { return (a->WaitUsecs() < b->WaitUsecs())\
388 if (w != _workers.end()) {
389 rc = std::chrono::microseconds((*w)->WaitUsecs());
Dwm::Thread::Queue class template definition.
Worker class for LoadBalancer.
Definition DwmLoadBalancer.hh:81
bool AddWork(InputIterator firstIter, InputIterator lastIter)
Adds work items for the worker.
Definition DwmLoadBalancer.hh:116
virtual bool ProcessWork(std::deque< ItemT > &items)
Process a deque of work items.
Definition DwmLoadBalancer.hh:224
void Run()
Runs the worker thread.
Definition DwmLoadBalancer.hh:195
virtual void ProcessWork(ItemT &item)=0
Pure virtual member to process a single work item.
void MaxWork(uint32_t maxItems)
Sets the maximum length of the worker's work queue.
Definition DwmLoadBalancer.hh:155
void Stop()
Stops the worker.
Definition DwmLoadBalancer.hh:175
bool AddWork(const ItemT &item)
Adds a work item for the worker.
Definition DwmLoadBalancer.hh:105
virtual ~Worker()
Destructor. Stops the worker thread.
Definition DwmLoadBalancer.hh:96
Worker(std::chrono::microseconds waitNotEmptyMicroseconds=std::chrono::microseconds(1000))
Constructs the worker.
Definition DwmLoadBalancer.hh:88
bool ReadyForWork(size_t numEntries) const
Returns true if the worker is ready for numEntries units of work.
Definition DwmLoadBalancer.hh:144
uint32_t QueueLength() const
Returns the current length of the worker's work queue.
Definition DwmLoadBalancer.hh:124
std::chrono::microseconds WaitUsecs() const
Returns the microseconds we'll wait for queue to be non-empty in our worker thread.
Definition DwmLoadBalancer.hh:234
bool IsRunning()
Returns true if the worker's thread is running.
Definition DwmLoadBalancer.hh:187
bool ReadyForWork() const
Returns true if the worker is ready for more work (has room in its work queue and is running).
Definition DwmLoadBalancer.hh:133
bool Start()
Starts the worker.
Definition DwmLoadBalancer.hh:163
A simple load balancer class template which balances work across Worker objects that each run in thei...
Definition DwmLoadBalancer.hh:75
bool AddWork(ItemT item)
Adds work to be done with load balancing.
Definition DwmLoadBalancer.hh:262
bool AddWork(InputIterator firstIter, InputIterator lastIter)
Adds work to be done with load balancing.
Definition DwmLoadBalancer.hh:296
void AddWorker(Worker *worker)
Adds the given worker to the load balancer.
Definition DwmLoadBalancer.hh:251
const std::vector< std::unique_ptr< Worker > > & Workers() const
Returns a const reference to the encapsulated workers.
Definition DwmLoadBalancer.hh:334
void Stop()
Calls Worker::Stop() on all encapsulated Worker objects.
Definition DwmLoadBalancer.hh:321
This template provides inter-thread first-in first-out (FIFO) queueing.
Definition DwmThreadQueue.hh:68
std::deque< _ValueType >::size_type Length() const
Returns the current length of the queue.
Definition DwmThreadQueue.hh:111
uint32_t Swap(std::deque< _ValueType > &c)
This member is a simple optimization for fetching the contents of the queue.
Definition DwmThreadQueue.hh:386
uint32_t MaxLength() const
Returns the max length of the queue.
Definition DwmThreadQueue.hh:93
bool PushBack(const _ValueType &value)
Inserts value on the back of the queue.
Definition DwmThreadQueue.hh:121
bool TimedWaitForNotEmpty(const std::chrono::duration< Rep, Period > &timeToWait)
Waits timeToWait for the queue to be non-empty.
Definition DwmThreadQueue.hh:321