Helios++
Helios software for LiDAR simulations
ResThreadPool.h
1 #pragma once
2 
3 #include <SimpleThreadPool.h>
4 #include <HeliosException.h>
5 
12 template <typename ... TaskArgs>
13 class ResThreadPool : public SimpleThreadPool<TaskArgs ...>{
14 protected:
22 
23 public:
24  // *** CONSTRUCTION / DESTRUCTION *** //
25  // ************************************ //
30  explicit ResThreadPool(std::size_t const _pool_size) :
31  SimpleThreadPool<TaskArgs ...>(_pool_size)
32  {
33  // Allocate
34  resourceSetAvailable = new bool[this->pool_size];
35 
36  // Initialize
37  for (std::size_t i = 0; i < this->pool_size; ++i){
38  resourceSetAvailable[i] = true;
39  }
40  }
41 
42  virtual ~ResThreadPool(){
43  // Release memory
44  delete[] resourceSetAvailable;
45  }
46 
47 protected:
48  // *** M E T H O D S *** //
49  // *********************** //
54  virtual inline int getAvailableResourceSetIndex() const {
55  for(size_t i = 0 ; i < this->pool_size ; i++){
56  if(resourceSetAvailable[i]) return i;
57  }
58  return -1;
59  }
60 
61 public:
66  template <typename Task>
67  void run_res_task(Task task){
68  boost::unique_lock<boost::mutex> lock(this->mutex_);
69 
70  // If no threads are available, by default wait for a thread to finish
71  if (0 == this->available_){
72  this->cond_.wait(lock);
73  }
74 
75  // Decrement count, indicating thread is no longer available
76  --(this->available_);
77 
78  // Get resource set index
79  int const resourceIdx = getAvailableResourceSetIndex();
80  resourceSetAvailable[resourceIdx] = false;
81 
82  // Unlock the mutex
83  lock.unlock();
84 
85  // Post a wrapped task into the queue
86  this->io_service_.post(
87  boost::bind(
89  this,
90  boost::function<void(TaskArgs ...)>(task),
91  resourceIdx
92  )
93  );
94  }
95 
104  template <typename Task>
105  bool try_run_res_task(Task task){
106  boost::unique_lock<boost::mutex> lock(this->mutex_);
107 
108  // If no threads are available, by default return false
109  if (0 == this->available_){
110  return false;
111  }
112 
113  // Decrement count, indicating thread is no longer available
114  --(this->available_);
115 
116  // Get resource set index
117  int const resourceIdx = getAvailableResourceSetIndex();
118  resourceSetAvailable[resourceIdx] = false;
119 
120  // Unlock the mutex
121  lock.unlock();
122 
123  // Post a wrapped task into the queue
124  this->io_service_.post(
125  boost::bind(
127  this,
128  boost::function<void(TaskArgs ...)>(task),
129  resourceIdx
130  )
131  );
132  return true;
133  }
134 
135 protected:
144  virtual void wrap_res_task(
145  boost::function<void(TaskArgs ...)> &task,
146  int const resourceIdx
147  ){
148  // Run the user supplied task.
149  try{
150  do_res_task(task, resourceIdx);
151  }
152  // Suppress all exceptions.
153  catch (const std::exception &e) {
154  std::stringstream ss;
155  ss << "ResThreadPool::wrap_res_task EXCEPTION: " << e.what();
156  logging::WARN(ss.str());
157  }
158 
159  // Task has finished, so increment count of available threads.
160  boost::unique_lock<boost::mutex> lock(this->mutex_);
161  ++(this->available_);
162  resourceSetAvailable[resourceIdx] = true;
163  lock.unlock();
164  this->cond_.notify_one();
165  }
166 
171  void do_task(
172  boost::function<void(TaskArgs ...)> &task
173  ) override {
174  throw HeliosException(
175  "ResThreadPool::do_task MUST NOT be invoked.\n"
176  "Please, avoid this call or override implementation"
177 
178  );
179  }
180 
188  virtual void do_res_task(
189  boost::function<void(TaskArgs ...)> &task,
190  int const resourceIdx
191  ) = 0;
192 
193 };
Base class for Helios exceptions.
Definition: HeliosException.h:12
Abstract class extending basic thread pool implementation to provide a basis layer to handle thread a...
Definition: ResThreadPool.h:13
void run_res_task(Task task)
Run a task with associated resources when there is an available thread for it.
Definition: ResThreadPool.h:67
bool try_run_res_task(Task task)
Run a task with associated resources. If there is not even a single available thread,...
Definition: ResThreadPool.h:105
virtual int getAvailableResourceSetIndex() const
Obtain the index of an available resource set.
Definition: ResThreadPool.h:54
bool * resourceSetAvailable
Array of flags specifying availability of resource sets.
Definition: ResThreadPool.h:21
void do_task(boost::function< void(TaskArgs ...)> &task) override
Throw exception when calling non resource do_task.
Definition: ResThreadPool.h:171
virtual void wrap_res_task(boost::function< void(TaskArgs ...)> &task, int const resourceIdx)
Wrap a task so that available threads count can be increased once provided task has been completed.
Definition: ResThreadPool.h:144
virtual void do_res_task(boost::function< void(TaskArgs ...)> &task, int const resourceIdx)=0
Invoke task with associated resources with corresponding arguments.
ResThreadPool(std::size_t const _pool_size)
Resource thread pool constructor.
Definition: ResThreadPool.h:30
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