I am trying to create a limited thread pool class using boost::asio. But I am stuck at one point can some one help me.
The only problem is the place where I should decrease counter?
code does not work as expected.
the problem is I don’t know when my thread will finish execution and how I will come to know that it has return to pool
#include <boost/asio.hpp>
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <boost/thread/mutex.hpp>
#include <stack>
using namespace std;
using namespace boost;
class ThreadPool
{
static int count;
int NoOfThread;
thread_group grp;
mutex mutex_;
asio::io_service io_service;
int counter;
stack<thread*> thStk ;
public:
ThreadPool(int num)
{
NoOfThread = num;
counter = 0;
mutex::scoped_lock lock(mutex_);
if(count == 0)
count++;
else
return;
for(int i=0 ; i<num ; ++i)
{
thStk.push(grp.create_thread(boost::bind(&asio::io_service::run, &io_service)));
}
}
~ThreadPool()
{
io_service.stop();
grp.join_all();
}
thread* getThread()
{
if(counter > NoOfThread)
{
cout<<"run out of threads \n";
return NULL;
}
counter++;
thread* ptr = thStk.top();
thStk.pop();
return ptr;
}
};
int ThreadPool::count = 0;
struct callable
{
void operator()()
{
cout<<"some task for thread \n";
}
};
int main( int argc, char * argv[] )
{
callable x;
ThreadPool pool(10);
thread* p = pool.getThread();
cout<<p->get_id();
//how i can assign some function to thread pointer ?
//how i can return thread pointer after work done so i can add
//it back to stack?
return 0;
}
In short, you need to wrap the user’s provided task with another function that will:
I may not be understanding all the requirements for this thread pool. Thus, for clarity, here is an explicit list as to what I believe are the requirements:
Before I provide an implementation, there are a few key points I would like to stress:
io_service::run(), and callable types are posted into the event queue, such as fromio_service::post().io_service::run()returns if there is no work pending in theio_service, theio_serviceis stopped, or an exception is thrown from a handler that the thread was running. To preventio_serivce::run()from returning when there is no unfinished work, theio_service::workclass can be used.object()syntax) instead of requiring a type (i.e. task must inherit fromprocess), provides more flexibility to the user. It allows the user to supply a task as a function pointer or a type providing a nullaryoperator().Implementation using
boost::asio:A few comments about the implementation:
boost::thread_interrupted, thenstd::terminate()is called. This is the the result of Boost.Thread’s exceptions in thread functions behavior. It is also worth reading Boost.Asio’s effect of exceptions thrown from handlers.taskviaboost::bind, then the nestedboost::bindwill fail to compile. One of the following options is required:taskcreated byboost::bind.boost::bindso thatboost::protectcould be used, asboost::protectonly functions properly on certain function objects.taskobject indirectly. I opted to useboost::functionfor readability at the cost of losing the exact type.boost::tuple, while slightly less readable, could also be used to preserve the exact type, as seen in the Boost.Asio’s serialization example.Application code can now use the
thread_pooltype non-intrusively:The
thread_poolcould be created without Boost.Asio, and may be slightly easier for maintainers, as they no longer need to know aboutBoost.Asiobehaviors, such as when doesio_service::run()return, and what is theio_service::workobject: