Helios++
Helios software for LiDAR simulations
MDThreadPool.h
1 #pragma once
2 
3 #include <SimpleThreadPool.h>
4 #include <HeliosException.h>
5 
6 #include <unordered_map>
7 
8 
21 template <typename MDType, typename ... TaskArgs>
22 class MDThreadPool : public SimpleThreadPool<TaskArgs ...>{
23 public:
24  // *** CONSTRUCTION / DESTRUCTION *** //
25  // ************************************ //
30  explicit MDThreadPool(std::size_t const _pool_size) :
31  SimpleThreadPool<TaskArgs ...>(_pool_size)
32  {setPendingTasks(0);}
33  virtual ~MDThreadPool(){}
34 
35 
36  // *** M E T H O D S *** //
37  // *********************** //
42  template <typename Task>
43  void run_md_task(Task task, MDType *data){
44  // Lock run task mutex
45  boost::unique_lock<boost::mutex> lock(this->mutex_);
46 
47  // Increment number of pending tasks
49 
50  // Unlock run task mutex
51  lock.unlock();
52 
53  // Post a wrapped task into the queue
54  this->io_service_.post(
55  boost::bind(
57  this,
58  boost::function<void(TaskArgs ...)>(task),
59  data
60  )
61  );
62  }
63 
73  template <typename Task>
74  bool try_run_md_task(Task task, MDType *data){
75  // Lock run task mutex
76  boost::unique_lock<boost::mutex> lock(this->mutex_);
77 
78  // Check pending tasks does not exceed max limit
79  if(getPendingTasks() >= this->pool_size){
80  lock.unlock();
81  return false;
82  }
83 
84  // Increment number of pending tasks
86 
87  // Unlock run task mutex
88  lock.unlock();
89 
90  // Post a wrapped task into the queue
91  this->io_service_.post(
92  boost::bind(
94  this,
95  boost::function<void(TaskArgs ...)>(task),
96  data
97  )
98  );
99  return true;
100  }
101 
105  void join() override {
106  boost::unique_lock<boost::mutex> lock(this->mutex_);
107  while(getPendingTasks() > 0){
108  this->cond_.wait(lock);
109  }
110  this->work_.reset(); // Allow works to finish normally
111  this->threads_.join_all(); // Wait for all threads to finish
112  }
113 
114 protected:
124  virtual void wrap_md_task(
125  boost::function<void(TaskArgs ...)> &task,
126  MDType *data
127  ){
128  // Run supplied data task
129  try{
130  do_md_task(task, data);
131  }
132  // Suppress all exceptions.
133  catch (const std::exception &e) {
134  std::stringstream ss;
135  ss << "MDThreadPool::wrap_md_task EXCEPTION: " << e.what();
136  logging::WARN(ss.str());
137  }
138 
139  // Task has finished, so increment count of available threads.
140  boost::unique_lock<boost::mutex> lock(this->mutex_);
142  if(getPendingTasks()==0){
143  lock.unlock();
144  this->cond_.notify_one();
145  }
146  }
147 
152  void do_task(
153  boost::function<void(TaskArgs ...)> &task
154  ) override {
155  throw HeliosException(
156  "MDThreadPool::do_task MUST NOT be invoked.\n"
157  "Please, avoid this call or override implementation"
158  );
159  }
160 
166  virtual void do_md_task(
167  boost::function<void(TaskArgs ...)> &task,
168  MDType *data
169  ) = 0;
170 
171 public:
172  // *** GETTERs and SETTERs *** //
173  // ***************************** //
178  virtual inline size_t getPendingTasks() {return this->available_;}
184  virtual inline size_t safeGetPendingTasks() {
185  boost::unique_lock<boost::mutex> lock(this->mutex_);
186  size_t const pTasks = getPendingTasks();
187  lock.unlock();
188  return pTasks;
189  }
194  virtual inline void setPendingTasks(size_t const pendingTasks)
195  {this->available_ = pendingTasks;}
201  virtual inline void safeSetPendingTasks(size_t const pendingTasks){
202  boost::unique_lock<boost::mutex> lock(this->mutex_);
203  setPendingTasks(pendingTasks);
204  lock.unlock();
205  }
213  virtual inline void subtractPendingTasks(size_t const amount){
215  }
221  virtual inline void safeSubtractPendingTasks(size_t const amount){
222  boost::unique_lock<boost::mutex> lock(this->mutex_);
223  subtractPendingTasks(amount);
224  lock.unlock();
225  }
229  virtual inline void increasePendingTasks() {++(this->available_);}
233  virtual inline void decreasePendingTasks() {--(this->available_);}
234 };
Base class for Helios exceptions.
Definition: HeliosException.h:12
Abstract class extending basic thread pool implementation to provide a basis layer to handle tasks wi...
Definition: MDThreadPool.h:22
virtual size_t safeGetPendingTasks()
Obtain the number of pending tasks to be computed in a thread safe way. It is, with proper handling o...
Definition: MDThreadPool.h:184
void join() override
Lock until all pending threads have finished.
Definition: MDThreadPool.h:105
virtual void subtractPendingTasks(size_t const amount)
Subtract specified amount of pending tasks.
Definition: MDThreadPool.h:213
virtual void increasePendingTasks()
Unitary increase the number of pending tasks to be computed.
Definition: MDThreadPool.h:229
virtual void setPendingTasks(size_t const pendingTasks)
Set the number of pending tasks to be computed.
Definition: MDThreadPool.h:194
void run_md_task(Task task, MDType *data)
Run a task with associated data without considering limit for max pending tasks.
Definition: MDThreadPool.h:43
virtual void wrap_md_task(boost::function< void(TaskArgs ...)> &task, MDType *data)
Wrap a data task so that pending tasks count can be increased once provided data task has been comple...
Definition: MDThreadPool.h:124
virtual void safeSetPendingTasks(size_t const pendingTasks)
Set the number of pending tasks to be computed in a thread safe way. It is, with proper handling of c...
Definition: MDThreadPool.h:201
virtual void do_md_task(boost::function< void(TaskArgs ...)> &task, MDType *data)=0
Invoke task with associated data.
void do_task(boost::function< void(TaskArgs ...)> &task) override
Throw exception when calling non data do_task.
Definition: MDThreadPool.h:152
virtual void safeSubtractPendingTasks(size_t const amount)
Subtract pending tasks in a thread safe way. It is, with proper handling of concurrency.
Definition: MDThreadPool.h:221
virtual void decreasePendingTasks()
Unitary decrease the number of pending tasks to be computed.
Definition: MDThreadPool.h:233
MDThreadPool(std::size_t const _pool_size)
Multiple data thread pool constructor.
Definition: MDThreadPool.h:30
virtual size_t getPendingTasks()
Obtain the number of pending tasks to be computed.
Definition: MDThreadPool.h:178
bool try_run_md_task(Task task, MDType *data)
Try to run a task with associated data. If the max limit of pending tasks has not been reached,...
Definition: MDThreadPool.h:74
Abstract class providing implementation of a simple thread pool which assigns tasks to threads.
Definition: SimpleThreadPool.h:12
std::size_t pool_size
Size of thread pool (number of threads)
Definition: ThreadPool.h:47
boost::mutex mutex_
Mutex to handle concurrent tasks.
Definition: SimpleThreadPool.h:26
boost::asio::io_service io_service_
Instance of boost input/output service for asynchronous data processing.
Definition: ThreadPool.h:36
boost::condition_variable cond_
Condition variable to handle tasks dispatching depending on available threads.
Definition: SimpleThreadPool.h:31
std::size_t available_
Number of available threads, those which are not currently performing a task.
Definition: SimpleThreadPool.h:22
boost::thread_group threads_
Group of threads.
Definition: ThreadPool.h:51
boost::asio::executor_work_guard< boost::asio::io_service::executor_type > work_
Instance of work guard to report the io service when it has pending tasks.
Definition: ThreadPool.h:43