spectrum2/libtransport/ThreadPool.cpp

128 lines
2.7 KiB
C++
Raw Permalink Normal View History

#include "transport/ThreadPool.h"
#include "transport/Logging.h"
#include "Swiften/SwiftenCompat.h"
namespace Transport {
2012-06-02 20:10:42 +05:30
DEFINE_LOGGER(logger, "ThreadPool")
2012-06-03 18:03:39 +05:30
ThreadPool::ThreadPool(Swift::EventLoop *loop, int maxthreads) : MAX_THREADS(maxthreads)
2012-06-02 20:10:42 +05:30
{
2012-06-03 18:03:39 +05:30
this->loop = loop;
2012-06-02 20:10:42 +05:30
activeThreads = 0;
worker = (boost::thread **) malloc(sizeof(boost::thread *) * MAX_THREADS);
2012-06-02 20:10:42 +05:30
for(int i=0 ; i<MAX_THREADS ; i++) {
worker[i] = NULL;
freeThreads.push(i);
}
onWorkerAvailable.connect(boost::bind(&ThreadPool::scheduleFromQueue, this));
}
ThreadPool::~ThreadPool()
{
for(int i=0; i<MAX_THREADS ; i++) {
if(worker[i]) {
delete worker[i];
}
}
free(worker);
2012-06-02 20:10:42 +05:30
while(!requestQueue.empty()) {
Thread *t = requestQueue.front(); requestQueue.pop();
delete t;
}
}
int ThreadPool::getActiveThreadCount()
2017-06-12 00:41:35 +02:00
{
2012-06-02 20:10:42 +05:30
int res;
2017-06-12 00:41:35 +02:00
count_lock.lock();
2012-06-02 20:10:42 +05:30
res = activeThreads;
count_lock.unlock();
return res;
}
void ThreadPool::updateActiveThreadCount(int k)
{
count_lock.lock();
activeThreads += k;
count_lock.unlock();
}
int ThreadPool::getFreeThread()
{
int res = -1;
pool_lock.lock();
if(!freeThreads.empty()){
res = freeThreads.front();
freeThreads.pop();
updateActiveThreadCount(-1);
}
pool_lock.unlock();
return res;
}
void ThreadPool::releaseThread(int i)
{
if(i < 0 || i > MAX_THREADS) return;
pool_lock.lock();
delete worker[i];
worker[i] = NULL;
freeThreads.push(i);
2017-06-12 00:41:35 +02:00
2012-06-02 20:10:42 +05:30
updateActiveThreadCount(1);
2017-06-12 00:41:35 +02:00
2012-06-02 20:10:42 +05:30
pool_lock.unlock();
}
void ThreadPool::cleandUp(Thread *t, int wid)
{
2017-06-12 00:41:35 +02:00
LOG4CXX_INFO(logger, "Cleaning up thread #" << t->getThreadID());
2012-06-02 20:10:42 +05:30
t->finalize();
delete t;
releaseThread(wid);
2017-06-12 00:41:35 +02:00
onWorkerAvailable();
2012-06-02 20:10:42 +05:30
}
void ThreadPool::scheduleFromQueue()
{
2017-06-12 00:41:35 +02:00
criticalregion.lock();
2012-06-02 20:10:42 +05:30
while(!requestQueue.empty()) {
int w = getFreeThread();
if(w == -1) break;
2017-06-12 00:41:35 +02:00
LOG4CXX_INFO(logger, "Worker Available. Creating thread #" << w);
2012-06-02 20:10:42 +05:30
Thread *t = requestQueue.front(); requestQueue.pop();
t->setThreadID(w);
worker[w] = new boost::thread(boost::bind(&ThreadPool::workerBody, this, _1, _2), t, w, loop);
2012-06-02 20:10:42 +05:30
updateActiveThreadCount(-1);
}
criticalregion.unlock();
}
void ThreadPool::runAsThread(Thread *t)
{
int w;
if((w = getFreeThread()) != -1) {
2017-06-12 00:41:35 +02:00
LOG4CXX_INFO(logger, "Creating thread #" << w);
2012-06-02 20:10:42 +05:30
t->setThreadID(w);
worker[w] = new boost::thread(boost::bind(&ThreadPool::workerBody, this, _1, _2), t, w, loop);
2012-06-02 20:10:42 +05:30
updateActiveThreadCount(-1);
}
else {
2017-06-12 00:41:35 +02:00
LOG4CXX_INFO(logger, "No workers available! adding to queue.");
2012-06-02 20:10:42 +05:30
requestQueue.push(t);
}
}
void ThreadPool::workerBody(Thread *t, int wid) {
2017-06-12 00:41:35 +02:00
LOG4CXX_INFO(logger, "Starting thread " << wid);
t->run();
loop->postEvent(boost::bind(&ThreadPool::cleandUp, this, t, wid), SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::EventOwner>());
}
}