2015-11-18 14:05:57 +01:00
|
|
|
#include "transport/ThreadPool.h"
|
|
|
|
#include "transport/Logging.h"
|
|
|
|
|
2016-09-12 18:20:58 +02:00
|
|
|
#include "Swiften/SwiftenCompat.h"
|
|
|
|
|
2015-11-24 12:26:26 +01:00
|
|
|
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;
|
2016-02-24 08:35:10 +01:00
|
|
|
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];
|
|
|
|
}
|
|
|
|
}
|
2016-02-24 08:35:10 +01:00
|
|
|
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);
|
2016-09-08 00:07:24 +02:00
|
|
|
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);
|
2016-09-08 00:07:24 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2015-11-24 12:26:26 +01:00
|
|
|
|
2016-09-08 00:07:24 +02:00
|
|
|
void ThreadPool::workerBody(Thread *t, int wid) {
|
2017-06-12 00:41:35 +02:00
|
|
|
LOG4CXX_INFO(logger, "Starting thread " << wid);
|
2016-09-08 00:07:24 +02:00
|
|
|
t->run();
|
|
|
|
loop->postEvent(boost::bind(&ThreadPool::cleandUp, this, t, wid), SWIFTEN_SHRPTR_NAMESPACE::shared_ptr<Swift::EventOwner>());
|
|
|
|
}
|
|
|
|
|
2015-11-24 12:26:26 +01:00
|
|
|
}
|