You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-29 08:21:15 +03:00
clang format apply
This commit is contained in:
@ -16,14 +16,14 @@
|
||||
MA 02110-1301, USA. */
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* 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/web/20100104101109/http://devguy.com/bb/viewtopic.php?t=460
|
||||
*
|
||||
***********************************************************************/
|
||||
*
|
||||
* 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/web/20100104101109/http://devguy.com/bb/viewtopic.php?t=460
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
/** @file */
|
||||
|
||||
@ -58,350 +58,344 @@ namespace threadpool
|
||||
// Taken from boost::thread_group and adapted
|
||||
class ThreadPoolGroup
|
||||
{
|
||||
private:
|
||||
ThreadPoolGroup(ThreadPoolGroup const&);
|
||||
ThreadPoolGroup& operator=(ThreadPoolGroup const&);
|
||||
public:
|
||||
ThreadPoolGroup() {}
|
||||
~ThreadPoolGroup()
|
||||
{
|
||||
for(std::list<boost::thread*>::iterator it=threads.begin(),end=threads.end();
|
||||
it!=end;
|
||||
++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
private:
|
||||
ThreadPoolGroup(ThreadPoolGroup const&);
|
||||
ThreadPoolGroup& operator=(ThreadPoolGroup const&);
|
||||
|
||||
template<typename F>
|
||||
boost::thread* create_thread(F threadfunc)
|
||||
public:
|
||||
ThreadPoolGroup()
|
||||
{
|
||||
}
|
||||
~ThreadPoolGroup()
|
||||
{
|
||||
for (std::list<boost::thread*>::iterator it = threads.begin(), end = threads.end(); it != end; ++it)
|
||||
{
|
||||
boost::lock_guard<boost::shared_mutex> guard(m);
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
boost::thread* create_thread(F threadfunc)
|
||||
{
|
||||
boost::lock_guard<boost::shared_mutex> guard(m);
|
||||
#if __cplusplus >= 201103L
|
||||
std::unique_ptr<boost::thread> new_thread(new boost::thread(threadfunc));
|
||||
std::unique_ptr<boost::thread> new_thread(new boost::thread(threadfunc));
|
||||
#else
|
||||
std::auto_ptr<boost::thread> new_thread(new boost::thread(threadfunc));
|
||||
std::auto_ptr<boost::thread> new_thread(new boost::thread(threadfunc));
|
||||
#endif
|
||||
threads.push_back(new_thread.get());
|
||||
return new_thread.release();
|
||||
}
|
||||
threads.push_back(new_thread.get());
|
||||
return new_thread.release();
|
||||
}
|
||||
|
||||
void add_thread(boost::thread* thrd)
|
||||
void add_thread(boost::thread* thrd)
|
||||
{
|
||||
if (thrd)
|
||||
{
|
||||
if(thrd)
|
||||
{
|
||||
boost::lock_guard<boost::shared_mutex> guard(m);
|
||||
threads.push_back(thrd);
|
||||
}
|
||||
boost::lock_guard<boost::shared_mutex> guard(m);
|
||||
threads.push_back(thrd);
|
||||
}
|
||||
}
|
||||
|
||||
void remove_thread(boost::thread* thrd)
|
||||
void remove_thread(boost::thread* thrd)
|
||||
{
|
||||
boost::lock_guard<boost::shared_mutex> guard(m);
|
||||
std::list<boost::thread*>::iterator const it = std::find(threads.begin(), threads.end(), thrd);
|
||||
if (it != threads.end())
|
||||
{
|
||||
boost::lock_guard<boost::shared_mutex> guard(m);
|
||||
std::list<boost::thread*>::iterator const it=std::find(threads.begin(),threads.end(),thrd);
|
||||
if(it!=threads.end())
|
||||
{
|
||||
threads.erase(it);
|
||||
}
|
||||
threads.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void join_all()
|
||||
void join_all()
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> guard(m);
|
||||
|
||||
for (std::list<boost::thread*>::iterator it = threads.begin(), end = threads.end(); it != end; ++it)
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> guard(m);
|
||||
|
||||
for(std::list<boost::thread*>::iterator it=threads.begin(),end=threads.end();
|
||||
it!=end;
|
||||
++it)
|
||||
{
|
||||
(*it)->join();
|
||||
}
|
||||
(*it)->join();
|
||||
}
|
||||
}
|
||||
|
||||
void interrupt_all()
|
||||
void interrupt_all()
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> guard(m);
|
||||
|
||||
for (std::list<boost::thread*>::iterator it = threads.begin(), end = threads.end(); it != end; ++it)
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> guard(m);
|
||||
|
||||
for(std::list<boost::thread*>::iterator it=threads.begin(),end=threads.end();
|
||||
it!=end;
|
||||
++it)
|
||||
{
|
||||
(*it)->interrupt();
|
||||
}
|
||||
(*it)->interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
size_t size() const
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> guard(m);
|
||||
return threads.size();
|
||||
}
|
||||
|
||||
void join_one(boost::thread::id id)
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> guard(m);
|
||||
for (std::list<boost::thread*>::iterator it = threads.begin(), end = threads.end(); it != end; ++it)
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> guard(m);
|
||||
return threads.size();
|
||||
if ((*it)->get_id() == id)
|
||||
{
|
||||
(*it)->join();
|
||||
threads.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void join_one(boost::thread::id id)
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> guard(m);
|
||||
for(std::list<boost::thread*>::iterator it=threads.begin(),end=threads.end();
|
||||
it!=end;
|
||||
++it)
|
||||
{
|
||||
if ((*it)->get_id() == id)
|
||||
{
|
||||
(*it)->join();
|
||||
threads.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
std::list<boost::thread*> threads;
|
||||
mutable boost::shared_mutex m;
|
||||
private:
|
||||
std::list<boost::thread*> threads;
|
||||
mutable boost::shared_mutex m;
|
||||
};
|
||||
|
||||
|
||||
/** @brief ThreadPool is a component for working with pools of threads and asynchronously
|
||||
* executing tasks. It is responsible for creating threads and tracking which threads are "busy"
|
||||
* and which are idle. Idle threads are utilized as "work" is added to the system.
|
||||
*/
|
||||
* executing tasks. It is responsible for creating threads and tracking which threads are "busy"
|
||||
* and which are idle. Idle threads are utilized as "work" is added to the system.
|
||||
*/
|
||||
class ThreadPool
|
||||
{
|
||||
public:
|
||||
typedef boost::function0<void> Functor_T;
|
||||
public:
|
||||
typedef boost::function0<void> Functor_T;
|
||||
|
||||
/*********************************************
|
||||
* ctor/dtor
|
||||
*
|
||||
*********************************************/
|
||||
/*********************************************
|
||||
* ctor/dtor
|
||||
*
|
||||
*********************************************/
|
||||
|
||||
/** @brief ctor
|
||||
*/
|
||||
EXPORT ThreadPool();
|
||||
/** @brief ctor
|
||||
*/
|
||||
EXPORT ThreadPool();
|
||||
|
||||
/** @brief ctor
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
EXPORT explicit ThreadPool( size_t maxThreads, size_t queueSize );
|
||||
/** @brief ctor
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
EXPORT explicit ThreadPool(size_t maxThreads, size_t queueSize);
|
||||
|
||||
/** @brief dtor
|
||||
*/
|
||||
EXPORT ~ThreadPool() throw();
|
||||
/** @brief dtor
|
||||
*/
|
||||
EXPORT ~ThreadPool() throw();
|
||||
|
||||
/*********************************************
|
||||
* accessors/mutators
|
||||
*
|
||||
*********************************************/
|
||||
/** @brief set the work queue size
|
||||
*
|
||||
* @param queueSize the size of the work queue
|
||||
*/
|
||||
EXPORT void setQueueSize(size_t queueSize);
|
||||
|
||||
/*********************************************
|
||||
* accessors/mutators
|
||||
*
|
||||
*********************************************/
|
||||
/** @brief set the work queue size
|
||||
*
|
||||
* @param queueSize the size of the work queue
|
||||
*/
|
||||
EXPORT void setQueueSize( size_t queueSize );
|
||||
/** @brief fet the work queue size
|
||||
*/
|
||||
inline size_t getQueueSize() const
|
||||
{
|
||||
return fQueueSize;
|
||||
}
|
||||
|
||||
/** @brief fet the work queue size
|
||||
*/
|
||||
inline size_t getQueueSize() const
|
||||
/** @brief set the maximum number of threads to be used to process
|
||||
* the work queue
|
||||
*
|
||||
* @param maxThreads the maximum number of threads
|
||||
*/
|
||||
EXPORT void setMaxThreads(size_t maxThreads);
|
||||
|
||||
/** @brief get the maximum number of threads
|
||||
*/
|
||||
inline size_t getMaxThreads() const
|
||||
{
|
||||
return fMaxThreads;
|
||||
}
|
||||
|
||||
/** @brief get the issued number of threads
|
||||
*/
|
||||
inline size_t getIssuedThreads()
|
||||
{
|
||||
return fIssued;
|
||||
}
|
||||
|
||||
/** @brief queue size accessor
|
||||
*
|
||||
*/
|
||||
inline uint32_t getWaiting() const
|
||||
{
|
||||
return waitingFunctorsSize;
|
||||
}
|
||||
|
||||
/*********************************************
|
||||
* operations
|
||||
*
|
||||
*********************************************/
|
||||
|
||||
/** @brief invoke a functor in a separate thread managed by the pool
|
||||
*
|
||||
* If all maxThreads are busy, threadfunc will be added to a work list and
|
||||
* will run when a thread comes free. If all threads are busy and there are
|
||||
* queueSize tasks already waiting, invoke() will block until a slot in the
|
||||
* queue comes free.
|
||||
*/
|
||||
EXPORT uint64_t invoke(const Functor_T& threadfunc);
|
||||
|
||||
/** @brief stop the threads
|
||||
*/
|
||||
EXPORT void stop();
|
||||
|
||||
/** @brief wait on all the threads to complete
|
||||
*/
|
||||
EXPORT void wait();
|
||||
|
||||
/** @brief Wait for a specific thread
|
||||
*/
|
||||
EXPORT void join(uint64_t thrHandle);
|
||||
|
||||
/** @brief Wait for a specific thread
|
||||
*/
|
||||
EXPORT void join(std::vector<uint64_t>& thrHandle);
|
||||
|
||||
/** @brief for use in debugging
|
||||
*/
|
||||
EXPORT void dump();
|
||||
|
||||
EXPORT std::string& name()
|
||||
{
|
||||
return fName;
|
||||
}
|
||||
|
||||
EXPORT void setName(std::string name)
|
||||
{
|
||||
fName = name;
|
||||
}
|
||||
EXPORT void setName(const char* name)
|
||||
{
|
||||
fName = name;
|
||||
}
|
||||
|
||||
EXPORT bool debug()
|
||||
{
|
||||
return fDebug;
|
||||
}
|
||||
|
||||
EXPORT void setDebug(bool d)
|
||||
{
|
||||
fDebug = d;
|
||||
}
|
||||
|
||||
friend class ThreadPoolMonitor;
|
||||
|
||||
protected:
|
||||
private:
|
||||
// Used internally to keep a handle associated with each functor for join()
|
||||
struct PoolFunction_T
|
||||
{
|
||||
uint64_t hndl;
|
||||
Functor_T functor;
|
||||
};
|
||||
|
||||
/** @brief initialize data memebers
|
||||
*/
|
||||
void init();
|
||||
|
||||
/** @brief add a functor to the list
|
||||
*/
|
||||
uint64_t addFunctor(const Functor_T& func);
|
||||
|
||||
/** @brief thread entry point
|
||||
*/
|
||||
void beginThread() throw();
|
||||
|
||||
void pruneThread();
|
||||
|
||||
ThreadPool(const ThreadPool&);
|
||||
ThreadPool& operator=(const ThreadPool&);
|
||||
|
||||
friend struct beginThreadFunc;
|
||||
|
||||
struct beginThreadFunc
|
||||
{
|
||||
beginThreadFunc(ThreadPool& impl) : fImpl(impl)
|
||||
{
|
||||
return fQueueSize;
|
||||
}
|
||||
|
||||
/** @brief set the maximum number of threads to be used to process
|
||||
* the work queue
|
||||
*
|
||||
* @param maxThreads the maximum number of threads
|
||||
*/
|
||||
EXPORT void setMaxThreads( size_t maxThreads );
|
||||
|
||||
/** @brief get the maximum number of threads
|
||||
*/
|
||||
inline size_t getMaxThreads() const
|
||||
void operator()()
|
||||
{
|
||||
return fMaxThreads;
|
||||
fImpl.beginThread();
|
||||
}
|
||||
|
||||
/** @brief get the issued number of threads
|
||||
*/
|
||||
inline size_t getIssuedThreads() { return fIssued; }
|
||||
ThreadPool& fImpl;
|
||||
};
|
||||
|
||||
/** @brief queue size accessor
|
||||
*
|
||||
*/
|
||||
inline uint32_t getWaiting() const
|
||||
struct NoOp
|
||||
{
|
||||
void operator()() const
|
||||
{
|
||||
return waitingFunctorsSize;
|
||||
}
|
||||
};
|
||||
|
||||
size_t fThreadCount;
|
||||
size_t fMaxThreads;
|
||||
size_t fQueueSize;
|
||||
|
||||
/*********************************************
|
||||
* operations
|
||||
*
|
||||
*********************************************/
|
||||
typedef std::list<PoolFunction_T> Container_T;
|
||||
Container_T fWaitingFunctors;
|
||||
Container_T::iterator fNextFunctor;
|
||||
|
||||
/** @brief invoke a functor in a separate thread managed by the pool
|
||||
*
|
||||
* If all maxThreads are busy, threadfunc will be added to a work list and
|
||||
* will run when a thread comes free. If all threads are busy and there are
|
||||
* queueSize tasks already waiting, invoke() will block until a slot in the
|
||||
* queue comes free.
|
||||
*/
|
||||
EXPORT uint64_t invoke(const Functor_T& threadfunc);
|
||||
uint32_t fIssued;
|
||||
boost::mutex fMutex;
|
||||
boost::condition_variable fThreadAvailable; // triggered when a thread is available
|
||||
boost::condition_variable fNeedThread; // triggered when a thread is needed
|
||||
ThreadPoolGroup fThreads;
|
||||
|
||||
/** @brief stop the threads
|
||||
*/
|
||||
EXPORT void stop();
|
||||
bool fStop;
|
||||
long fGeneralErrors;
|
||||
long fFunctorErrors;
|
||||
uint32_t waitingFunctorsSize;
|
||||
uint64_t fNextHandle;
|
||||
|
||||
/** @brief wait on all the threads to complete
|
||||
*/
|
||||
EXPORT void wait();
|
||||
|
||||
/** @brief Wait for a specific thread
|
||||
*/
|
||||
EXPORT void join(uint64_t thrHandle);
|
||||
|
||||
/** @brief Wait for a specific thread
|
||||
*/
|
||||
EXPORT void join(std::vector<uint64_t>& thrHandle);
|
||||
|
||||
/** @brief for use in debugging
|
||||
*/
|
||||
EXPORT void dump();
|
||||
|
||||
EXPORT std::string& name()
|
||||
{
|
||||
return fName;
|
||||
}
|
||||
|
||||
EXPORT void setName(std::string name)
|
||||
{
|
||||
fName = name;
|
||||
}
|
||||
EXPORT void setName(const char* name)
|
||||
{
|
||||
fName = name;
|
||||
}
|
||||
|
||||
EXPORT bool debug()
|
||||
{
|
||||
return fDebug;
|
||||
}
|
||||
|
||||
EXPORT void setDebug(bool d)
|
||||
{
|
||||
fDebug = d;
|
||||
}
|
||||
|
||||
|
||||
friend class ThreadPoolMonitor;
|
||||
protected:
|
||||
|
||||
private:
|
||||
// Used internally to keep a handle associated with each functor for join()
|
||||
struct PoolFunction_T
|
||||
{
|
||||
uint64_t hndl;
|
||||
Functor_T functor;
|
||||
};
|
||||
|
||||
/** @brief initialize data memebers
|
||||
*/
|
||||
void init();
|
||||
|
||||
/** @brief add a functor to the list
|
||||
*/
|
||||
uint64_t addFunctor(const Functor_T& func);
|
||||
|
||||
/** @brief thread entry point
|
||||
*/
|
||||
void beginThread() throw();
|
||||
|
||||
void pruneThread();
|
||||
|
||||
ThreadPool(const ThreadPool&);
|
||||
ThreadPool& operator = (const ThreadPool&);
|
||||
|
||||
friend struct beginThreadFunc;
|
||||
|
||||
struct beginThreadFunc
|
||||
{
|
||||
beginThreadFunc(ThreadPool& impl)
|
||||
: fImpl(impl)
|
||||
{}
|
||||
|
||||
void operator() ()
|
||||
{
|
||||
fImpl.beginThread();
|
||||
}
|
||||
|
||||
ThreadPool& fImpl;
|
||||
};
|
||||
|
||||
struct NoOp
|
||||
{
|
||||
void operator () () const
|
||||
{}
|
||||
};
|
||||
|
||||
size_t fThreadCount;
|
||||
size_t fMaxThreads;
|
||||
size_t fQueueSize;
|
||||
|
||||
typedef std::list<PoolFunction_T> Container_T;
|
||||
Container_T fWaitingFunctors;
|
||||
Container_T::iterator fNextFunctor;
|
||||
|
||||
uint32_t fIssued;
|
||||
boost::mutex fMutex;
|
||||
boost::condition_variable fThreadAvailable; // triggered when a thread is available
|
||||
boost::condition_variable fNeedThread; // triggered when a thread is needed
|
||||
ThreadPoolGroup fThreads;
|
||||
|
||||
bool fStop;
|
||||
long fGeneralErrors;
|
||||
long fFunctorErrors;
|
||||
uint32_t waitingFunctorsSize;
|
||||
uint64_t fNextHandle;
|
||||
|
||||
std::string fName; // Optional to add a name to the pool for debugging.
|
||||
bool fDebug;
|
||||
boost::mutex fInitMutex;
|
||||
boost::mutex fPruneMutex;
|
||||
boost::condition_variable fPruneThreadEnd;
|
||||
boost::thread* fPruneThread;
|
||||
std::stack<boost::thread::id> fPruneThreads; // A list of stale thread IDs to be joined
|
||||
std::string fName; // Optional to add a name to the pool for debugging.
|
||||
bool fDebug;
|
||||
boost::mutex fInitMutex;
|
||||
boost::mutex fPruneMutex;
|
||||
boost::condition_variable fPruneThreadEnd;
|
||||
boost::thread* fPruneThread;
|
||||
std::stack<boost::thread::id> fPruneThreads; // A list of stale thread IDs to be joined
|
||||
};
|
||||
|
||||
// This class, if instantiated, will continuously log details about the indicated threadpool
|
||||
// The log will end up in /var/log/mariadb/columnstore/trace/threadpool_<name>.log
|
||||
class ThreadPoolMonitor
|
||||
{
|
||||
public:
|
||||
ThreadPoolMonitor(ThreadPool* pool) : fPool(pool), fLog(NULL)
|
||||
{
|
||||
}
|
||||
public:
|
||||
ThreadPoolMonitor(ThreadPool* pool) : fPool(pool), fLog(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
~ThreadPoolMonitor()
|
||||
~ThreadPoolMonitor()
|
||||
{
|
||||
if (fLog)
|
||||
{
|
||||
if (fLog)
|
||||
{
|
||||
delete fLog;
|
||||
}
|
||||
delete fLog;
|
||||
}
|
||||
}
|
||||
|
||||
void operator()();
|
||||
private:
|
||||
//defaults okay
|
||||
//ThreadPoolMonitor(const ThreadPoolMonitor& rhs);
|
||||
//ThreadPoolMonitor& operator=(const ThreadPoolMonitor& rhs);
|
||||
ThreadPool* fPool;
|
||||
std::ofstream* fLog;
|
||||
void operator()();
|
||||
|
||||
private:
|
||||
// defaults okay
|
||||
// ThreadPoolMonitor(const ThreadPoolMonitor& rhs);
|
||||
// ThreadPoolMonitor& operator=(const ThreadPoolMonitor& rhs);
|
||||
ThreadPool* fPool;
|
||||
std::ofstream* fLog;
|
||||
};
|
||||
|
||||
} // namespace threadpool
|
||||
} // namespace threadpool
|
||||
|
||||
#undef EXPORT
|
||||
|
||||
|
Reference in New Issue
Block a user