1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-29 08:21:15 +03:00

Reformat all code to coding standard

This commit is contained in:
Andrew Hutchings
2017-10-26 17:18:17 +01:00
parent 4985f3456e
commit 01446d1e22
1296 changed files with 403852 additions and 353747 deletions

View File

@ -37,144 +37,162 @@ namespace threadpool
{
PriorityThreadPool::PriorityThreadPool(uint targetWeightPerRun, uint highThreads,
uint midThreads, uint lowThreads, uint ID) :
_stop(false), weightPerRun(targetWeightPerRun), id(ID)
uint midThreads, uint lowThreads, uint ID) :
_stop(false), weightPerRun(targetWeightPerRun), id(ID)
{
for (uint32_t i = 0; i < highThreads; i++)
threads.create_thread(ThreadHelper(this, HIGH));
for (uint32_t i = 0; i < midThreads; i++)
threads.create_thread(ThreadHelper(this, MEDIUM));
for (uint32_t i = 0; i < lowThreads; i++)
threads.create_thread(ThreadHelper(this, LOW));
cout << "started " << highThreads << " high, " << midThreads << " med, " << lowThreads
<< " low.\n";
threadCounts[HIGH] = highThreads;
threadCounts[MEDIUM] = midThreads;
threadCounts[LOW] = lowThreads;
for (uint32_t i = 0; i < highThreads; i++)
threads.create_thread(ThreadHelper(this, HIGH));
for (uint32_t i = 0; i < midThreads; i++)
threads.create_thread(ThreadHelper(this, MEDIUM));
for (uint32_t i = 0; i < lowThreads; i++)
threads.create_thread(ThreadHelper(this, LOW));
cout << "started " << highThreads << " high, " << midThreads << " med, " << lowThreads
<< " low.\n";
threadCounts[HIGH] = highThreads;
threadCounts[MEDIUM] = midThreads;
threadCounts[LOW] = lowThreads;
}
PriorityThreadPool::~PriorityThreadPool()
{
stop();
stop();
}
void PriorityThreadPool::addJob(const Job &job, bool useLock)
void PriorityThreadPool::addJob(const Job& job, bool useLock)
{
mutex::scoped_lock lk(mutex, defer_lock_t());
mutex::scoped_lock lk(mutex, defer_lock_t());
if (useLock)
lk.lock();
if (useLock)
lk.lock();
if (job.priority > 66)
jobQueues[HIGH].push_back(job);
else if (job.priority > 33)
jobQueues[MEDIUM].push_back(job);
else
jobQueues[LOW].push_back(job);
if (job.priority > 66)
jobQueues[HIGH].push_back(job);
else if (job.priority > 33)
jobQueues[MEDIUM].push_back(job);
else
jobQueues[LOW].push_back(job);
if (useLock)
newJob.notify_one();
if (useLock)
newJob.notify_one();
}
void PriorityThreadPool::removeJobs(uint32_t id)
{
list<Job>::iterator it;
list<Job>::iterator it;
mutex::scoped_lock lk(mutex);
mutex::scoped_lock lk(mutex);
for (uint32_t i = 0; i < _COUNT; i++)
for (it = jobQueues[i].begin(); it != jobQueues[i].end();)
if (it->id == id)
it = jobQueues[i].erase(it);
else
++it;
for (uint32_t i = 0; i < _COUNT; i++)
for (it = jobQueues[i].begin(); it != jobQueues[i].end();)
if (it->id == id)
it = jobQueues[i].erase(it);
else
++it;
}
PriorityThreadPool::Priority PriorityThreadPool::pickAQueue(Priority preference)
{
if (!jobQueues[preference].empty())
return preference;
else if (!jobQueues[HIGH].empty())
return HIGH;
else if (!jobQueues[MEDIUM].empty())
return MEDIUM;
else
return LOW;
if (!jobQueues[preference].empty())
return preference;
else if (!jobQueues[HIGH].empty())
return HIGH;
else if (!jobQueues[MEDIUM].empty())
return MEDIUM;
else
return LOW;
}
void PriorityThreadPool::threadFcn(const Priority preferredQueue) throw()
{
Priority queue;
uint32_t weight, i;
vector<Job> runList;
vector<bool> reschedule;
uint32_t rescheduleCount;
uint32_t queueSize;
Priority queue;
uint32_t weight, i;
vector<Job> runList;
vector<bool> reschedule;
uint32_t rescheduleCount;
uint32_t queueSize;
while (!_stop) {
while (!_stop)
{
mutex::scoped_lock lk(mutex);
mutex::scoped_lock lk(mutex);
queue = pickAQueue(preferredQueue);
if (jobQueues[queue].empty()) {
newJob.wait(lk);
continue;
}
queue = pickAQueue(preferredQueue);
queueSize = jobQueues[queue].size();
weight = 0;
// 3 conditions stop this thread from grabbing all jobs in the queue
//
// 1: The weight limit has been exceeded
// 2: The queue is empty
// 3: It has grabbed more than half of the jobs available &
// should leave some to the other threads
if (jobQueues[queue].empty())
{
newJob.wait(lk);
continue;
}
while ((weight < weightPerRun) && (!jobQueues[queue].empty())
&& (runList.size() <= queueSize/2)) {
runList.push_back(jobQueues[queue].front());
jobQueues[queue].pop_front();
weight += runList.back().weight;
}
lk.unlock();
queueSize = jobQueues[queue].size();
weight = 0;
// 3 conditions stop this thread from grabbing all jobs in the queue
//
// 1: The weight limit has been exceeded
// 2: The queue is empty
// 3: It has grabbed more than half of the jobs available &
// should leave some to the other threads
reschedule.resize(runList.size());
rescheduleCount = 0;
for (i = 0; i < runList.size() && !_stop; i++) {
try {
reschedule[i] = false;
reschedule[i] = (*(runList[i].functor))();
if (reschedule[i])
rescheduleCount++;
}
catch (std::exception &e) {
cerr << e.what() << endl;
}
}
while ((weight < weightPerRun) && (!jobQueues[queue].empty())
&& (runList.size() <= queueSize / 2))
{
runList.push_back(jobQueues[queue].front());
jobQueues[queue].pop_front();
weight += runList.back().weight;
}
// no real work was done, prevent intensive busy waiting
if (rescheduleCount == runList.size())
usleep(1000);
lk.unlock();
if (rescheduleCount > 0) {
lk.lock();
for (i = 0; i < runList.size(); i++)
if (reschedule[i])
addJob(runList[i], false);
if (rescheduleCount > 1)
newJob.notify_all();
else
newJob.notify_one();
lk.unlock();
}
runList.clear();
}
reschedule.resize(runList.size());
rescheduleCount = 0;
for (i = 0; i < runList.size() && !_stop; i++)
{
try
{
reschedule[i] = false;
reschedule[i] = (*(runList[i].functor))();
if (reschedule[i])
rescheduleCount++;
}
catch (std::exception& e)
{
cerr << e.what() << endl;
}
}
// no real work was done, prevent intensive busy waiting
if (rescheduleCount == runList.size())
usleep(1000);
if (rescheduleCount > 0)
{
lk.lock();
for (i = 0; i < runList.size(); i++)
if (reschedule[i])
addJob(runList[i], false);
if (rescheduleCount > 1)
newJob.notify_all();
else
newJob.notify_one();
lk.unlock();
}
runList.clear();
}
}
void PriorityThreadPool::stop()
{
_stop = true;
threads.join_all();
_stop = true;
threads.join_all();
}
} // namespace threadpool

View File

@ -44,30 +44,33 @@ class PriorityThreadPool
{
public:
class Functor {
public:
virtual ~Functor() { };
// as of 12/3/13, all implementors return 0 and -1. -1 will cause
class Functor
{
public:
virtual ~Functor() { };
// as of 12/3/13, all implementors return 0 and -1. -1 will cause
// this thread pool to reschedule the job, 0 will throw it away on return.
virtual int operator()() = 0;
};
virtual int operator()() = 0;
};
//typedef boost::function0<int> Functor;
struct Job {
Job() : weight(1), priority(0), id(0) { }
boost::shared_ptr<Functor> functor;
uint32_t weight;
uint32_t priority;
uint32_t id;
};
struct Job
{
Job() : weight(1), priority(0), id(0) { }
boost::shared_ptr<Functor> functor;
uint32_t weight;
uint32_t priority;
uint32_t id;
};
enum Priority {
LOW,
MEDIUM,
HIGH,
_COUNT
};
enum Priority
{
LOW,
MEDIUM,
HIGH,
_COUNT
};
/*********************************************
* ctor/dtor
@ -78,11 +81,11 @@ public:
*/
PriorityThreadPool(uint targetWeightPerRun, uint highThreads, uint midThreads,
uint lowThreads, uint id = 0);
uint lowThreads, uint id = 0);
virtual ~PriorityThreadPool();
void removeJobs(uint32_t id);
void addJob(const Job &job, bool useLock = true);
void addJob(const Job& job, bool useLock = true);
void stop();
/** @brief for use in debugging
@ -92,16 +95,20 @@ public:
protected:
private:
struct ThreadHelper {
ThreadHelper(PriorityThreadPool *impl, Priority queue) : ptp(impl), preferredQueue(queue) { }
void operator()() { ptp->threadFcn(preferredQueue); }
PriorityThreadPool *ptp;
struct ThreadHelper
{
ThreadHelper(PriorityThreadPool* impl, Priority queue) : ptp(impl), preferredQueue(queue) { }
void operator()()
{
ptp->threadFcn(preferredQueue);
}
PriorityThreadPool* ptp;
Priority preferredQueue;
};
explicit PriorityThreadPool();
explicit PriorityThreadPool(const PriorityThreadPool &);
PriorityThreadPool & operator=(const PriorityThreadPool &);
explicit PriorityThreadPool(const PriorityThreadPool&);
PriorityThreadPool& operator=(const PriorityThreadPool&);
Priority pickAQueue(Priority preference);
void threadFcn(const Priority preferredQueue) throw();

View File

@ -66,11 +66,11 @@ private:
}
foo(int i):
fData(i)
{}
fData(i)
{}
foo(const foo& copy)
: fData(copy.fData)
: fData(copy.fData)
{}
int fData;
@ -116,10 +116,10 @@ CPPUNIT_TEST_SUITE_REGISTRATION( ThreadPoolTestSuite );
#include <cppunit/ui/text/TestRunner.h>
int main( int argc, char **argv)
int main( int argc, char** argv)
{
CppUnit::TextUi::TestRunner runner;
CppUnit::TestFactoryRegistry &registry = CppUnit::TestFactoryRegistry::getRegistry();
CppUnit::TestFactoryRegistry& registry = CppUnit::TestFactoryRegistry::getRegistry();
runner.addTest( registry.makeTest() );
bool wasSuccessful = runner.run( "", false );
return (wasSuccessful ? 0 : 1);

View File

@ -36,13 +36,13 @@ namespace threadpool
{
ThreadPool::ThreadPool()
:fMaxThreads( 0 ), fQueueSize( 0 )
: fMaxThreads( 0 ), fQueueSize( 0 )
{
init();
}
ThreadPool::ThreadPool( size_t maxThreads, size_t queueSize )
:fMaxThreads( maxThreads ), fQueueSize( queueSize )
: fMaxThreads( maxThreads ), fQueueSize( queueSize )
{
init();
}
@ -70,7 +70,7 @@ void ThreadPool::init()
fDebug = false;
fStop = false;
fNextFunctor = fWaitingFunctors.end();
fNextHandle=1;
fNextHandle = 1;
}
void ThreadPool::setQueueSize(size_t queueSize)
@ -117,19 +117,23 @@ void ThreadPool::join(uint64_t thrHandle)
Container_T::iterator iter;
Container_T::iterator end = fWaitingFunctors.end();
bool foundit = false;
for (iter = fWaitingFunctors.begin(); iter != end; ++iter)
{
foundit = false;
if (iter->hndl == thrHandle)
{
foundit = true;
break;
}
}
if (!foundit)
{
break;
}
fThreadAvailable.wait(lock1);
}
}
@ -143,11 +147,13 @@ void ThreadPool::join(std::vector<uint64_t>& thrHandle)
Container_T::iterator iter;
Container_T::iterator end = fWaitingFunctors.end();
bool foundit = false;
for (iter = fWaitingFunctors.begin(); iter != end; ++iter)
{
foundit = false;
std::vector<uint64_t>::iterator thrIter;
std::vector<uint64_t>::iterator thrEnd = thrHandle.end();
for (thrIter = thrHandle.begin(); thrIter != thrEnd; ++thrIter)
{
if (iter->hndl == *thrIter)
@ -156,24 +162,28 @@ void ThreadPool::join(std::vector<uint64_t>& thrHandle)
break;
}
}
if (foundit == true)
{
break;
}
}
// If we didn't find any of the handles, then all are complete
if (!foundit)
{
break;
}
fThreadAvailable.wait(lock1);
}
}
uint64_t ThreadPool::invoke(const Functor_T &threadfunc)
uint64_t ThreadPool::invoke(const Functor_T& threadfunc)
{
boost::mutex::scoped_lock lock1(fMutex);
uint64_t thrHandle=0;
uint64_t thrHandle = 0;
for (;;)
{
try
@ -208,7 +218,7 @@ uint64_t ThreadPool::invoke(const Functor_T &threadfunc)
{
ostringstream oss;
oss << "invoke: Starting thread " << fThreadCount << " max " << fMaxThreads
<< " queue " << fQueueSize;
<< " queue " << fQueueSize;
logging::Message::Args args;
logging::Message message(0);
args.add(oss.str());
@ -247,6 +257,7 @@ uint64_t ThreadPool::invoke(const Functor_T &threadfunc)
logging::MessageLog ml(lid);
ml.logWarningMessage( message );
}
fThreadAvailable.wait(lock1);
}
catch (...)
@ -265,7 +276,8 @@ void ThreadPool::beginThread() throw()
try
{
boost::mutex::scoped_lock lock1(fMutex);
boost::system_time timeout = boost::get_system_time()+boost::posix_time::minutes(10);
boost::system_time timeout = boost::get_system_time() + boost::posix_time::minutes(10);
for (;;)
{
if (fStop)
@ -290,7 +302,8 @@ void ThreadPool::beginThread() throw()
--fThreadCount;
return;
}
timeout = boost::get_system_time()+boost::posix_time::minutes(10);
timeout = boost::get_system_time() + boost::posix_time::minutes(10);
}
}
}
@ -302,11 +315,12 @@ void ThreadPool::beginThread() throw()
Container_T::iterator todo = fNextFunctor++;
++fIssued;
lock1.unlock();
try
{
todo->functor();
}
catch (exception &e)
catch (exception& e)
{
++fFunctorErrors;
#ifndef NOLOGGING
@ -320,13 +334,14 @@ void ThreadPool::beginThread() throw()
ml.logErrorMessage( message );
#endif
}
lock1.lock();
--fIssued;
--waitingFunctorsSize;
fWaitingFunctors.erase(todo);
}
timeout = boost::get_system_time()+boost::posix_time::minutes(10);
timeout = boost::get_system_time() + boost::posix_time::minutes(10);
fThreadAvailable.notify_all();
}
}
@ -385,7 +400,7 @@ void ThreadPool::beginThread() throw()
}
}
uint64_t ThreadPool::addFunctor(const Functor_T &func)
uint64_t ThreadPool::addFunctor(const Functor_T& func)
{
bool bAtEnd = false;
@ -397,10 +412,12 @@ uint64_t ThreadPool::addFunctor(const Functor_T &func)
poolFunction.functor = func;
fWaitingFunctors.push_back(poolFunction);
waitingFunctorsSize++;
if (bAtEnd)
{
--fNextFunctor;
}
return fNextHandle++;
}
@ -417,6 +434,7 @@ void ThreadPoolMonitor::operator()()
ostringstream filename;
filename << "/var/log/mariadb/columnstore/trace/ThreadPool_" << fPool->name() << ".log";
fLog = new ofstream(filename.str().c_str());
for (;;)
{
if (!fLog || !fLog->is_open())
@ -432,6 +450,7 @@ void ThreadPoolMonitor::operator()()
ml.logWarningMessage( message );
return;
}
// Get a timestamp for output.
struct tm tm;
struct timeval tv;
@ -440,17 +459,17 @@ void ThreadPoolMonitor::operator()()
localtime_r(&tv.tv_sec, &tm);
(*fLog) << setfill('0')
<< setw(2) << tm.tm_hour << ':'
<< setw(2) << tm.tm_min << ':'
<< setw(2) << tm.tm_sec
<< '.'
<< setw(4) << tv.tv_usec/100
<< " Name " << fPool->fName
<< " Active " << fPool->waitingFunctorsSize
<< " Most " << fPool->fThreadCount
<< " Max " << fPool->fMaxThreads
<< " Q " << fPool->fQueueSize
<< endl;
<< setw(2) << tm.tm_hour << ':'
<< setw(2) << tm.tm_min << ':'
<< setw(2) << tm.tm_sec
<< '.'
<< setw(4) << tv.tv_usec / 100
<< " Name " << fPool->fName
<< " Active " << fPool->waitingFunctorsSize
<< " Most " << fPool->fThreadCount
<< " Max " << fPool->fMaxThreads
<< " Q " << fPool->fQueueSize
<< endl;
// struct timespec req = { 0, 1000 * 100 }; //100 usec
// nanosleep(&req, 0);

View File

@ -17,11 +17,11 @@
/***********************************************************************
*
* Work dervied from Devguy.com's Open Source C++ thread pool implementation
* Work dervied from Devguy.com's Open Source C++ thread pool implementation
* released under public domain:
* http://web.archive.org/liveweb/http://dgpctk.cvs.sourceforge.net/viewvc/dgpctk/dgc%2B%2B/include/dg/thread/threadpool.h?revision=1.22&content-type=text%2Fplain
* http://web.archive.org/liveweb/http://dgpctk.cvs.sourceforge.net/viewvc/dgpctk/dgc%2B%2B/include/dg/thread/threadpool.h?revision=1.22&content-type=text%2Fplain
*
* http://web.archive.org/web/20100104101109/http://devguy.com/bb/viewtopic.php?t=460
* http://web.archive.org/web/20100104101109/http://devguy.com/bb/viewtopic.php?t=460
*
***********************************************************************/
@ -62,7 +62,7 @@ public:
/*********************************************
* ctor/dtor
*
*
*********************************************/
/** @brief ctor
@ -74,10 +74,10 @@ public:
* @param maxThreads the maximum number of threads in this pool. This is the maximum number
* of simultaneuous operations that can go on.
* @param queueSize the maximum number of work tasks in the queue. This is the maximum
* number of jobs that can queue up in the work list before invoke() blocks.
* If 0, then threads never block and total threads may
* exceed maxThreads. Nothing waits. Thread count will
* idle down to maxThreads when less work is required.
* number of jobs that can queue up in the work list before invoke() blocks.
* If 0, then threads never block and total threads may
* exceed maxThreads. Nothing waits. Thread count will
* idle down to maxThreads when less work is required.
*/
EXPORT explicit ThreadPool( size_t maxThreads, size_t queueSize );
@ -88,7 +88,7 @@ public:
/*********************************************
* accessors/mutators
*
*
*********************************************/
/** @brief set the work queue size
*
@ -98,7 +98,10 @@ public:
/** @brief fet the work queue size
*/
inline size_t getQueueSize() const { return fQueueSize; }
inline size_t getQueueSize() const
{
return fQueueSize;
}
/** @brief set the maximum number of threads to be used to process
* the work queue
@ -109,17 +112,23 @@ public:
/** @brief get the maximum number of threads
*/
inline size_t getMaxThreads() const { return fMaxThreads; }
inline size_t getMaxThreads() const
{
return fMaxThreads;
}
/** @brief queue size accessor
*
*/
inline uint32_t getWaiting() const { return waitingFunctorsSize; }
inline uint32_t getWaiting() const
{
return waitingFunctorsSize;
}
/*********************************************
* operations
*
*
*********************************************/
/** @brief invoke a functor in a separate thread managed by the pool
@ -129,7 +138,7 @@ public:
* queueSize tasks already waiting, invoke() will block until a slot in the
* queue comes free.
*/
EXPORT uint64_t invoke(const Functor_T &threadfunc);
EXPORT uint64_t invoke(const Functor_T& threadfunc);
/** @brief stop the threads
*/
@ -151,16 +160,31 @@ public:
*/
EXPORT void dump();
EXPORT std::string& name() {return fName;}
EXPORT std::string& name()
{
return fName;
}
EXPORT void setName(std::string name) {fName = name;}
EXPORT void setName(const char* name) {fName = name;}
EXPORT void setName(std::string name)
{
fName = name;
}
EXPORT void setName(const char* name)
{
fName = name;
}
EXPORT bool debug() {return fDebug;}
EXPORT bool debug()
{
return fDebug;
}
EXPORT void setDebug(bool d) {fDebug = d;}
EXPORT void setDebug(bool d)
{
fDebug = d;
}
friend class ThreadPoolMonitor;
friend class ThreadPoolMonitor;
protected:
private:
@ -177,7 +201,7 @@ private:
/** @brief add a functor to the list
*/
uint64_t addFunctor(const Functor_T &func);
uint64_t addFunctor(const Functor_T& func);
/** @brief thread entry point
*/
@ -192,7 +216,7 @@ private:
struct beginThreadFunc
{
beginThreadFunc(ThreadPool& impl)
: fImpl(impl)
: fImpl(impl)
{}
void operator() ()
@ -200,7 +224,7 @@ private:
fImpl.beginThread();
}
ThreadPool &fImpl;
ThreadPool& fImpl;
};
struct NoOp
@ -226,11 +250,11 @@ private:
bool fStop;
long fGeneralErrors;
long fFunctorErrors;
uint32_t waitingFunctorsSize;
uint64_t fNextHandle;
uint32_t waitingFunctorsSize;
uint64_t fNextHandle;
std::string fName; // Optional to add a name to the pool for debugging.
bool fDebug;
std::string fName; // Optional to add a name to the pool for debugging.
bool fDebug;
};
// This class, if instantiated, will continuously log details about the indicated threadpool
@ -238,25 +262,25 @@ private:
class ThreadPoolMonitor
{
public:
ThreadPoolMonitor(ThreadPool* pool) : fPool(pool), fLog(NULL)
{
}
ThreadPoolMonitor(ThreadPool* pool) : fPool(pool), fLog(NULL)
{
}
~ThreadPoolMonitor()
{
if (fLog)
{
delete fLog;
}
}
~ThreadPoolMonitor()
{
if (fLog)
{
delete fLog;
}
}
void operator()();
void operator()();
private:
//defaults okay
//ThreadPoolMonitor(const ThreadPoolMonitor& rhs);
//ThreadPoolMonitor& operator=(const ThreadPoolMonitor& rhs);
ThreadPool* fPool;
std::ofstream* fLog;
//defaults okay
//ThreadPoolMonitor(const ThreadPoolMonitor& rhs);
//ThreadPoolMonitor& operator=(const ThreadPoolMonitor& rhs);
ThreadPool* fPool;
std::ofstream* fLog;
};
} // namespace threadpool

View File

@ -35,96 +35,114 @@ boost::mutex mutex;
const string timeNow()
{
time_t outputTime = time(0);
struct tm ltm;
char buf[32]; //ctime(3) says at least 26
size_t len = 0;
time_t outputTime = time(0);
struct tm ltm;
char buf[32]; //ctime(3) says at least 26
size_t len = 0;
#ifdef _MSC_VER
asctime_s(buf, 32, localtime_r(&outputTime, &ltm));
asctime_s(buf, 32, localtime_r(&outputTime, &ltm));
#else
asctime_r(localtime_r(&outputTime, &ltm), buf);
asctime_r(localtime_r(&outputTime, &ltm), buf);
#endif
len = strlen(buf);
if (len > 0) --len;
if (buf[len] == '\n') buf[len] = 0;
return buf;
len = strlen(buf);
if (len > 0) --len;
if (buf[len] == '\n') buf[len] = 0;
return buf;
}
// Functor class
struct foo
{
int64_t fData;
int64_t fThd;
string start;
bool running;
int64_t fData;
int64_t fThd;
string start;
bool running;
void operator ()()
{
start = timeNow();
void operator ()()
{
start = timeNow();
std::cout << "foo thd = " << fThd << " start " << start << std::endl;
for (int64_t i = 0; i < 1024*1024*(fThd+0)*128; i++)
// simulate some work
fData++;
std::cout << "foo thd = " << fThd << " start " << start << std::endl;
boost::mutex::scoped_lock lock(mutex);
std::cout << "foo thd = " << fThd << " start " << start << " fin " << timeNow() << std::endl;
}
for (int64_t i = 0; i < 1024 * 1024 * (fThd + 0) * 128; i++)
// simulate some work
fData++;
foo(int64_t i) : fThd(i), fData(i), running(true) {start=timeNow();}
boost::mutex::scoped_lock lock(mutex);
std::cout << "foo thd = " << fThd << " start " << start << " fin " << timeNow() << std::endl;
}
foo(const foo& copy) : fData(copy.fData), fThd(copy.fThd), start(copy.start), running(copy.running) {std::cout << "new foo " << fThd << endl;}
foo(int64_t i) : fThd(i), fData(i), running(true)
{
start = timeNow();
}
~foo() {running=false;}
foo(const foo& copy) : fData(copy.fData), fThd(copy.fThd), start(copy.start), running(copy.running)
{
std::cout << "new foo " << fThd << endl;
}
~foo()
{
running = false;
}
};
int main( int argc, char **argv)
int main( int argc, char** argv)
{
threadpool::ThreadPool pool( 20, 10 );
std::vector<uint64_t> hndl;
hndl.reserve(10);
int t1 = hndl.capacity();
uint64_t testHndl;
uint64_t thdhndl=999;
int64_t thd = 1;
boost::function0<void> foofunc;
boost::function0<void> foofunc2;
for (int64_t y = 0; y < 1; y++)
{
threadpool::ThreadPool pool( 20, 10 );
std::vector<uint64_t> hndl;
hndl.reserve(10);
int t1 = hndl.capacity();
uint64_t testHndl;
uint64_t thdhndl = 999;
int64_t thd = 1;
boost::function0<void> foofunc;
boost::function0<void> foofunc2;
for (int64_t y = 0; y < 1; y++)
{
foo bar(y);
// foofunc = bar;
// foofunc2 = foofunc;
std::cout << "Done with assign" << std::endl;
std::cout << "Done with assign" << std::endl;
for (int64_t i = 0; i < 1; ++i)
{
bar.fThd=thd++;
thdhndl = pool.invoke(bar);
if (y<10)
{
hndl.push_back(thdhndl);
}
if (y == 0)
{
testHndl = thdhndl;
}
bar.fThd = thd++;
thdhndl = pool.invoke(bar);
if (y < 10)
{
hndl.push_back(thdhndl);
}
if (y == 0)
{
testHndl = thdhndl;
}
}
boost::mutex::scoped_lock lock(mutex);
}
// Wait until all of the queued up and in-progress work has finished
std::cout << "Threads for join " << hndl.size() << std::endl;
pool.dump();
std::cout << "*** JOIN 1 ***" << std::endl;
pool.join(testHndl);
pool.dump();
std::cout << "*** JOIN 10 ***" << std::endl;
pool.join(hndl);
pool.dump();
std::cout << "*** WAIT ***" << std::endl;
pool.wait();
pool.dump();
sleep(2);
return 0;
}
// Wait until all of the queued up and in-progress work has finished
std::cout << "Threads for join " << hndl.size() << std::endl;
pool.dump();
std::cout << "*** JOIN 1 ***" << std::endl;
pool.join(testHndl);
pool.dump();
std::cout << "*** JOIN 10 ***" << std::endl;
pool.join(hndl);
pool.dump();
std::cout << "*** WAIT ***" << std::endl;
pool.wait();
pool.dump();
sleep(2);
return 0;
}

View File

@ -35,18 +35,18 @@ namespace threadpool
{
WeightedThreadPool::WeightedThreadPool()
:fMaxThreadWeight(0), fMaxThreads( 0 ), fQueueSize( 0 )
: fMaxThreadWeight(0), fMaxThreads( 0 ), fQueueSize( 0 )
{
init();
}
WeightedThreadPool::WeightedThreadPool( size_t maxThreadWeight, size_t maxThreads, size_t queueSize )
:fMaxThreadWeight(maxThreadWeight), fMaxThreads( maxThreads ), fQueueSize( queueSize )
: fMaxThreadWeight(maxThreadWeight), fMaxThreads( maxThreads ), fQueueSize( queueSize )
{
init();
if (fQueueSize == 0)
fQueueSize = fMaxThreads*2;
fQueueSize = fMaxThreads * 2;
}
@ -57,7 +57,7 @@ WeightedThreadPool::~WeightedThreadPool() throw()
{
stop();
}
catch(...)
catch (...)
{}
}
@ -67,9 +67,9 @@ void WeightedThreadPool::init()
fThreadCount = 0;
fGeneralErrors = 0;
fFunctorErrors = 0;
fWaitingFunctorsSize = 0;
fWaitingFunctorsWeight=0;
issued = 0;
fWaitingFunctorsSize = 0;
fWaitingFunctorsWeight = 0;
issued = 0;
fStop = false;
// fThreadCreated = new NoOp();
fNextFunctor = fWaitingFunctors.end();
@ -97,7 +97,7 @@ void WeightedThreadPool::setMaxThreadWeight(size_t maxWeight)
}
void WeightedThreadPool::setThreadCreatedListener(const Functor_T &f)
void WeightedThreadPool::setThreadCreatedListener(const Functor_T& f)
{
// fThreadCreated = f;
}
@ -120,40 +120,45 @@ void WeightedThreadPool::wait()
while (fWaitingFunctorsSize > 0)
{
//cout << "waiting ..." << endl;
//cout << "waiting ..." << endl;
fThreadAvailable.wait(lock1);
//cerr << "woke!" << endl;
//cerr << "woke!" << endl;
}
}
void WeightedThreadPool::removeJobs(uint32_t id)
{
boost::mutex::scoped_lock lock1(fMutex);
Container_T::iterator it;
boost::mutex::scoped_lock lock1(fMutex);
Container_T::iterator it;
it = fNextFunctor;
while (it != fWaitingFunctors.end()) {
if (it->id == id) {
fWaitingFunctorsWeight -= it->functorWeight;
fWaitingFunctorsSize--;
if (it == fNextFunctor) {
fWaitingFunctors.erase(fNextFunctor++);
it = fNextFunctor;
}
else
fWaitingFunctors.erase(it++);
}
else
++it;
}
it = fNextFunctor;
while (it != fWaitingFunctors.end())
{
if (it->id == id)
{
fWaitingFunctorsWeight -= it->functorWeight;
fWaitingFunctorsSize--;
if (it == fNextFunctor)
{
fWaitingFunctors.erase(fNextFunctor++);
it = fNextFunctor;
}
else
fWaitingFunctors.erase(it++);
}
else
++it;
}
}
void WeightedThreadPool::invoke(const Functor_T &threadfunc, uint32_t functor_weight,
uint32_t id)
void WeightedThreadPool::invoke(const Functor_T& threadfunc, uint32_t functor_weight,
uint32_t id)
{
boost::mutex::scoped_lock lock1(fMutex);
for(;;)
for (;;)
{
try
{
@ -175,11 +180,11 @@ void WeightedThreadPool::invoke(const Functor_T &threadfunc, uint32_t functor_we
bAdded = true;
}
// add a thread is necessary
// add a thread is necessary
if ( fThreadCount < fMaxThreads)
{
++fThreadCount;
//cout << "\t++invoke() tcnt=" << fThreadCount << endl;
//cout << "\t++invoke() tcnt=" << fThreadCount << endl;
lock1.unlock();
fThreads.create_thread(beginThreadFunc(*this));
@ -192,8 +197,9 @@ void WeightedThreadPool::invoke(const Functor_T &threadfunc, uint32_t functor_we
lock1.lock();
continue;
}
//else
// cout << "invoke() no thread created c=" << fThreadCount << " m=" << fMaxThreads << endl;
//else
// cout << "invoke() no thread created c=" << fThreadCount << " m=" << fMaxThreads << endl;
if (bAdded)
{
@ -203,7 +209,7 @@ void WeightedThreadPool::invoke(const Functor_T &threadfunc, uint32_t functor_we
fThreadAvailable.wait(lock1);
}
catch(...)
catch (...)
{
++fGeneralErrors;
throw;
@ -215,13 +221,14 @@ void WeightedThreadPool::invoke(const Functor_T &threadfunc, uint32_t functor_we
void WeightedThreadPool::beginThread() throw()
{
vector<bool> reschedule;
vector<bool> reschedule;
try
{
// fThreadCreated();
boost::mutex::scoped_lock lock1(fMutex);
for(;;)
for (;;)
{
if (fStop)
break;
@ -233,78 +240,90 @@ void WeightedThreadPool::beginThread() throw()
}
else
{
vector<Container_T::iterator> todoList;
int i, num = (fWaitingFunctorsSize - issued);
Container_T::const_iterator iter;
uint32_t weight=0;
vector<Container_T::iterator> todoList;
int i, num = (fWaitingFunctorsSize - issued);
Container_T::const_iterator iter;
uint32_t weight = 0;
for (i = 0; i < num && weight < fMaxThreadWeight; i++) {
weight += (*fNextFunctor).functorWeight;
todoList.push_back(fNextFunctor++);
}
issued+=i;
num=i;
for (i = 0; i < num && weight < fMaxThreadWeight; i++)
{
weight += (*fNextFunctor).functorWeight;
todoList.push_back(fNextFunctor++);
}
issued += i;
num = i;
lock1.unlock();
//cerr << "beginThread() " << num
// << " jobs - fWaitingFunctorsSize=" << fWaitingFunctorsSize
// << " fWaitingFunctorsWeight=" << fWaitingFunctorsWeight
// << " weight=" << weight
// << " issued=" << issued << " todo=" << todoList.size()
// << " fThreadCount=" << fThreadCount << endl;
i = 0;
reschedule.resize(num);
bool allWereRescheduled = true, someWereRescheduled = false;
while (i < num) {
try {
for (; i < num; i++) {
reschedule[i] = false; // in case of exception in the next line
reschedule[i] = ((*todoList[i]).functor)();
allWereRescheduled &= reschedule[i];
someWereRescheduled |= reschedule[i];
}
}
catch(exception &e) {
i++;
++fFunctorErrors;
cerr << e.what() << endl;
}
}
// no real work was done, prevent intensive busy waiting
if (allWereRescheduled)
usleep(1000);
//cerr << "beginThread() " << num
// << " jobs - fWaitingFunctorsSize=" << fWaitingFunctorsSize
// << " fWaitingFunctorsWeight=" << fWaitingFunctorsWeight
// << " weight=" << weight
// << " issued=" << issued << " todo=" << todoList.size()
// << " fThreadCount=" << fThreadCount << endl;
//cout << "running " << i << "/" << num << " functor" <<endl;
lock1.lock();
i = 0;
reschedule.resize(num);
bool allWereRescheduled = true, someWereRescheduled = false;
if (someWereRescheduled) {
for (i = 0; i < num; i++)
if (reschedule[i])
addFunctor((*todoList[i]).functor, (*todoList[i]).functorWeight,
(*todoList[i]).id);
if (num > 1)
fNeedThread.notify_all();
else
fNeedThread.notify_one();
}
while (i < num)
{
try
{
for (; i < num; i++)
{
reschedule[i] = false; // in case of exception in the next line
reschedule[i] = ((*todoList[i]).functor)();
allWereRescheduled &= reschedule[i];
someWereRescheduled |= reschedule[i];
}
}
catch (exception& e)
{
i++;
++fFunctorErrors;
cerr << e.what() << endl;
}
}
issued -= num;
for (i = 0; i < num; i++) {
fWaitingFunctorsWeight-=(*todoList[i]).functorWeight;
fWaitingFunctors.erase(todoList[i]);
}
fWaitingFunctorsSize -= num;
// no real work was done, prevent intensive busy waiting
if (allWereRescheduled)
usleep(1000);
//if (fWaitingFunctorsSize != fWaitingFunctors.size()) ;
// cerr << "num=" << num << " cleaned=" << i << " size="
// << fWaitingFunctorsSize << " list size="
// << fWaitingFunctors.size()
// << " w="<<fWaitingFunctorsWeight << endl;
//cout << "running " << i << "/" << num << " functor" <<endl;
lock1.lock();
if (someWereRescheduled)
{
for (i = 0; i < num; i++)
if (reschedule[i])
addFunctor((*todoList[i]).functor, (*todoList[i]).functorWeight,
(*todoList[i]).id);
if (num > 1)
fNeedThread.notify_all();
else
fNeedThread.notify_one();
}
issued -= num;
for (i = 0; i < num; i++)
{
fWaitingFunctorsWeight -= (*todoList[i]).functorWeight;
fWaitingFunctors.erase(todoList[i]);
}
fWaitingFunctorsSize -= num;
//if (fWaitingFunctorsSize != fWaitingFunctors.size()) ;
// cerr << "num=" << num << " cleaned=" << i << " size="
// << fWaitingFunctorsSize << " list size="
// << fWaitingFunctors.size()
// << " w="<<fWaitingFunctorsWeight << endl;
fThreadAvailable.notify_all();
}
}
}
@ -329,12 +348,12 @@ void WeightedThreadPool::beginThread() throw()
ml.logErrorMessage( message );
}
catch(...)
catch (...)
{
}
}
catch(...)
catch (...)
{
++fGeneralErrors;
@ -352,27 +371,27 @@ void WeightedThreadPool::beginThread() throw()
ml.logErrorMessage( message );
}
catch(...)
catch (...)
{
}
}
}
void WeightedThreadPool::addFunctor(const Functor_T &func, uint32_t functor_weight,
uint32_t id)
void WeightedThreadPool::addFunctor(const Functor_T& func, uint32_t functor_weight,
uint32_t id)
{
bool bAtEnd=false;
bool bAtEnd = false;
if (fNextFunctor == fWaitingFunctors.end())
bAtEnd = true;
//cout << "addFunctor() w=" << fWaitingFunctorsWeight
// << " s=" << fWaitingFunctorsSize << " i=" << id << endl;
//cout << "addFunctor() w=" << fWaitingFunctorsWeight
// << " s=" << fWaitingFunctorsSize << " i=" << id << endl;
FunctorListItem fl = {func, functor_weight, id};
FunctorListItem fl = {func, functor_weight, id};
fWaitingFunctors.push_back(fl);
fWaitingFunctorsSize++;
fWaitingFunctorsWeight+=functor_weight;
fWaitingFunctorsSize++;
fWaitingFunctorsWeight += functor_weight;
if (bAtEnd)
{

View File

@ -51,7 +51,7 @@ public:
/*********************************************
* ctor/dtor
*
*
*********************************************/
/** @brief ctor
@ -74,7 +74,7 @@ public:
/*********************************************
* accessors/mutators
*
*
*********************************************/
/** @brief set the work queue size
*
@ -84,7 +84,10 @@ public:
/** @brief fet the work queue size
*/
inline size_t getQueueSize() const { return fQueueSize; }
inline size_t getQueueSize() const
{
return fQueueSize;
}
/** @brief set the maximum number of threads to be used to process
* the work queue
@ -95,11 +98,14 @@ public:
/** @brief get the maximum number of threads
*/
inline size_t getMaxThreads() const { return fMaxThreads; }
inline size_t getMaxThreads() const
{
return fMaxThreads;
}
/** @brief set the maximum processing weight of a thread to be
* submitted for execution from the existing jobs
* scheduled in the work queue
* scheduled in the work queue
*
* @param maxWeight for execution
*/
@ -107,25 +113,34 @@ public:
/** @brief get the maximum number of threads
*/
inline uint32_t getMaxThreadWeight() const { return fMaxThreadWeight; }
inline uint32_t getMaxThreadWeight() const
{
return fMaxThreadWeight;
}
/** @brief register a functor to be called when a new thread
* is created
*/
void setThreadCreatedListener(const Functor_T &f) ;
void setThreadCreatedListener(const Functor_T& f) ;
/** @brief queue size accessor
*
*/
inline uint32_t getWaiting() const { return fWaitingFunctorsSize; }
inline uint32_t getWaiting() const
{
return fWaitingFunctorsSize;
}
inline uint32_t getWeight() const { return fWaitingFunctorsWeight; }
inline uint32_t getWeight() const
{
return fWaitingFunctorsWeight;
}
void removeJobs(uint32_t id);
/*********************************************
* operations
*
*
*********************************************/
/** @brief invoke a functor in a separate thread managed by the pool
@ -135,7 +150,7 @@ public:
* queueSize tasks already waiting, invoke() will block until a slot in the
* queue comes free.
*/
void invoke(const Functor_T &threadfunc, uint32_t functor_weight, uint32_t id);
void invoke(const Functor_T& threadfunc, uint32_t functor_weight, uint32_t id);
/** @brief stop the threads
*/
@ -158,7 +173,7 @@ private:
/** @brief add a functor to the list
*/
void addFunctor(const Functor_T &func, uint32_t functor_weight, uint32_t id);
void addFunctor(const Functor_T& func, uint32_t functor_weight, uint32_t id);
/** @brief thread entry point
*/
@ -173,7 +188,7 @@ private:
struct beginThreadFunc
{
beginThreadFunc(WeightedThreadPool& impl)
: fImpl(impl)
: fImpl(impl)
{}
void operator() ()
@ -181,14 +196,14 @@ private:
fImpl.beginThread();
}
WeightedThreadPool &fImpl;
WeightedThreadPool& fImpl;
};
struct NoOp
{
void operator () () const
{}
};
};
size_t fThreadCount;
size_t fMaxThreadWeight;
@ -196,18 +211,19 @@ private:
size_t fQueueSize;
//typedef std::list<Functor_T> Container_T;
struct FunctorListItemStruct {
Functor_T functor;
uint32_t functorWeight;
uint32_t id;
};
struct FunctorListItemStruct
{
Functor_T functor;
uint32_t functorWeight;
uint32_t id;
};
typedef FunctorListItemStruct FunctorListItem;
typedef FunctorListItemStruct FunctorListItem;
typedef std::list<FunctorListItem> Container_T;
Container_T fWaitingFunctors;
Container_T::iterator fNextFunctor;
uint32_t issued;
uint32_t issued;
boost::mutex fMutex;
boost::condition fThreadAvailable; // triggered when a thread is available
boost::condition fNeedThread; // triggered when a thread is needed
@ -216,8 +232,8 @@ private:
bool fStop;
long fGeneralErrors;
long fFunctorErrors;
uint16_t fWaitingFunctorsSize;
uint16_t fWaitingFunctorsWeight;
uint16_t fWaitingFunctorsSize;
uint16_t fWaitingFunctorsWeight;
};

View File

@ -34,52 +34,52 @@ using namespace std;
int thecount = 0;
boost::mutex mutex;
// Functor class
// Functor class
struct foo
{
void operator ()()
{
for (int i = 0; i < 1024*1024*10; i++)
// simulate some work
fData++;
void operator ()()
{
for (int i = 0; i < 1024 * 1024 * 10; i++)
// simulate some work
fData++;
//boost::mutex::scoped_lock lock(mutex);
//std::cout << "foo count = " << ++thecount << " " << fData << std::endl;
}
//boost::mutex::scoped_lock lock(mutex);
//std::cout << "foo count = " << ++thecount << " " << fData << std::endl;
}
foo(int i):
fData(i)
foo(int i):
fData(i)
{}
foo(const foo& copy)
: fData(copy.fData)
{}
foo(const foo& copy)
: fData(copy.fData)
{}
int fData;
int fData;
};
int main( int argc, char **argv)
int main( int argc, char** argv)
{
threadpool::WeightedThreadPool pool( 100, 10, 5 );
threadpool::WeightedThreadPool pool( 100, 10, 5 );
for (int y = 0; y < 10; y++)
{
for (int y = 0; y < 10; y++)
{
foo bar(y);
for (int i = 0; i < 10; ++i)
{
pool.invoke(bar, 25);
pool.invoke(bar, 25);
}
boost::mutex::scoped_lock lock(mutex);
std::cout << "count = " << ++thecount << std::endl;
// Wait until all of the queued up and in-progress work has finished
pool.wait();
pool.dump();
}
}
}