|
@@ -2,136 +2,126 @@
|
|
|
|
|
|
|
|
namespace BansheeEngine
|
|
namespace BansheeEngine
|
|
|
{
|
|
{
|
|
|
- class PooledThread
|
|
|
|
|
|
|
+ PooledThread::PooledThread(const String& name)
|
|
|
|
|
+ :mName(name), mIdle(true), mThreadStarted(false),
|
|
|
|
|
+ mThreadReady(false), mIdleTime(0)
|
|
|
{
|
|
{
|
|
|
- public:
|
|
|
|
|
- PooledThread()
|
|
|
|
|
- :mIdle(true), mThreadStarted(false),
|
|
|
|
|
- mThreadReady(false), mIdleTime(0)
|
|
|
|
|
- {
|
|
|
|
|
- CM_THREAD_CREATE(t, std::bind(&PooledThread::run, this));
|
|
|
|
|
|
|
+ CM_THREAD_CREATE(t, std::bind(&PooledThread::run, this));
|
|
|
|
|
|
|
|
- CM_LOCK_MUTEX_NAMED(mMutex, lock);
|
|
|
|
|
|
|
+ CM_LOCK_MUTEX_NAMED(mMutex, lock);
|
|
|
|
|
|
|
|
- while(!mThreadStarted)
|
|
|
|
|
- CM_THREAD_WAIT(mStartedCond, mMutex, lock);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ while(!mThreadStarted)
|
|
|
|
|
+ CM_THREAD_WAIT(mStartedCond, mMutex, lock);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- ~PooledThread()
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ PooledThread::~PooledThread()
|
|
|
|
|
+ {
|
|
|
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- void start(std::function<void()> workerMethod)
|
|
|
|
|
|
|
+ void PooledThread::start(std::function<void()> workerMethod)
|
|
|
|
|
+ {
|
|
|
{
|
|
{
|
|
|
- {
|
|
|
|
|
- CM_LOCK_MUTEX(mMutex);
|
|
|
|
|
- mWorkerMethod = workerMethod;
|
|
|
|
|
- mThreadReady = true;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- CM_THREAD_NOTIFY_ONE(mReadyCond);
|
|
|
|
|
|
|
+ CM_LOCK_MUTEX(mMutex);
|
|
|
|
|
+ mWorkerMethod = workerMethod;
|
|
|
|
|
+ mThreadReady = true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void run()
|
|
|
|
|
- {
|
|
|
|
|
- {
|
|
|
|
|
- CM_LOCK_MUTEX(mMutex);
|
|
|
|
|
- mThreadStarted = true;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- CM_THREAD_NOTIFY_ONE(mStartedCond);
|
|
|
|
|
|
|
+ CM_THREAD_NOTIFY_ONE(mReadyCond);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- while(true)
|
|
|
|
|
- {
|
|
|
|
|
- std::function<void()> worker = nullptr;
|
|
|
|
|
|
|
+ void PooledThread::run()
|
|
|
|
|
+ {
|
|
|
|
|
+ onThreadStarted(mName);
|
|
|
|
|
|
|
|
- {
|
|
|
|
|
- CM_LOCK_MUTEX_NAMED(mMutex, lock);
|
|
|
|
|
|
|
+ {
|
|
|
|
|
+ CM_LOCK_MUTEX(mMutex);
|
|
|
|
|
+ mThreadStarted = true;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- while(!mThreadReady)
|
|
|
|
|
- CM_THREAD_WAIT(mReadyCond, mMutex, lock);
|
|
|
|
|
|
|
+ CM_THREAD_NOTIFY_ONE(mStartedCond);
|
|
|
|
|
|
|
|
- if(mWorkerMethod == nullptr)
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ while(true)
|
|
|
|
|
+ {
|
|
|
|
|
+ std::function<void()> worker = nullptr;
|
|
|
|
|
|
|
|
- worker = mWorkerMethod;
|
|
|
|
|
- mIdle = false;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ {
|
|
|
|
|
+ CM_LOCK_MUTEX_NAMED(mMutex, lock);
|
|
|
|
|
|
|
|
- worker();
|
|
|
|
|
|
|
+ while(!mThreadReady)
|
|
|
|
|
+ CM_THREAD_WAIT(mReadyCond, mMutex, lock);
|
|
|
|
|
|
|
|
|
|
+ if(mWorkerMethod == nullptr)
|
|
|
{
|
|
{
|
|
|
- CM_LOCK_MUTEX(mMutex);
|
|
|
|
|
-
|
|
|
|
|
- mIdle = true;
|
|
|
|
|
- mIdleTime = std::time(nullptr);
|
|
|
|
|
- mThreadReady = false;
|
|
|
|
|
|
|
+ onThreadEnded(mName);
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ worker = mWorkerMethod;
|
|
|
|
|
+ mIdle = false;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- void destroy()
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ worker();
|
|
|
|
|
+
|
|
|
{
|
|
{
|
|
|
CM_LOCK_MUTEX(mMutex);
|
|
CM_LOCK_MUTEX(mMutex);
|
|
|
- mWorkerMethod = nullptr;
|
|
|
|
|
- mThreadReady = true;
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- CM_THREAD_NOTIFY_ONE(mReadyCond);
|
|
|
|
|
- CM_THREAD_JOIN((*mThread));
|
|
|
|
|
- CM_THREAD_DESTROY(mThread);
|
|
|
|
|
|
|
+ mIdle = true;
|
|
|
|
|
+ mIdleTime = std::time(nullptr);
|
|
|
|
|
+ mThreadReady = false;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- bool isIdle()
|
|
|
|
|
|
|
+ void PooledThread::destroy()
|
|
|
|
|
+ {
|
|
|
{
|
|
{
|
|
|
CM_LOCK_MUTEX(mMutex);
|
|
CM_LOCK_MUTEX(mMutex);
|
|
|
-
|
|
|
|
|
- return mIdle;
|
|
|
|
|
|
|
+ mWorkerMethod = nullptr;
|
|
|
|
|
+ mThreadReady = true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- time_t idleTime()
|
|
|
|
|
- {
|
|
|
|
|
- CM_LOCK_MUTEX(mMutex);
|
|
|
|
|
|
|
+ CM_THREAD_NOTIFY_ONE(mReadyCond);
|
|
|
|
|
+ CM_THREAD_JOIN((*mThread));
|
|
|
|
|
+ CM_THREAD_DESTROY(mThread);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- return (time(nullptr) - mIdleTime);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ bool PooledThread::isIdle()
|
|
|
|
|
+ {
|
|
|
|
|
+ CM_LOCK_MUTEX(mMutex);
|
|
|
|
|
|
|
|
- std::function<void()> mWorkerMethod;
|
|
|
|
|
|
|
+ return mIdle;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- bool mIdle;
|
|
|
|
|
- bool mThreadStarted;
|
|
|
|
|
- bool mThreadReady;
|
|
|
|
|
|
|
+ time_t PooledThread::idleTime()
|
|
|
|
|
+ {
|
|
|
|
|
+ CM_LOCK_MUTEX(mMutex);
|
|
|
|
|
|
|
|
- time_t mIdleTime;
|
|
|
|
|
|
|
+ return (time(nullptr) - mIdleTime);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- CM_THREAD_TYPE* mThread;
|
|
|
|
|
- CM_MUTEX(mMutex);
|
|
|
|
|
- CM_THREAD_SYNCHRONISER(mStartedCond);
|
|
|
|
|
- CM_THREAD_SYNCHRONISER(mReadyCond);
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ void PooledThread::setName(const String& name)
|
|
|
|
|
+ {
|
|
|
|
|
+ mName = name;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- ThreadPool::ThreadPool(UINT32 threadCapacity, UINT32 maxCapacity, UINT32 idleTimeout)
|
|
|
|
|
|
|
+ ThreadPoolBase::ThreadPoolBase(UINT32 threadCapacity, UINT32 maxCapacity, UINT32 idleTimeout)
|
|
|
:mDefaultCapacity(threadCapacity), mMaxCapacity(maxCapacity), mIdleTimeout(idleTimeout), mAge(0)
|
|
:mDefaultCapacity(threadCapacity), mMaxCapacity(maxCapacity), mIdleTimeout(idleTimeout), mAge(0)
|
|
|
{
|
|
{
|
|
|
- for(UINT32 i = 0; i < mDefaultCapacity; i++)
|
|
|
|
|
- {
|
|
|
|
|
- mThreads.push_back(createThread());
|
|
|
|
|
- }
|
|
|
|
|
|
|
+
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- ThreadPool::~ThreadPool()
|
|
|
|
|
|
|
+ ThreadPoolBase::~ThreadPoolBase()
|
|
|
{
|
|
{
|
|
|
stopAll();
|
|
stopAll();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void ThreadPool::run(std::function<void()> workerMethod)
|
|
|
|
|
|
|
+ void ThreadPoolBase::run(const String& name, std::function<void()> workerMethod)
|
|
|
{
|
|
{
|
|
|
- getThread()->start(workerMethod);
|
|
|
|
|
|
|
+ getThread(name)->start(workerMethod);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void ThreadPool::stopAll()
|
|
|
|
|
|
|
+ void ThreadPoolBase::stopAll()
|
|
|
{
|
|
{
|
|
|
CM_LOCK_MUTEX(mMutex);
|
|
CM_LOCK_MUTEX(mMutex);
|
|
|
for(auto& thread : mThreads)
|
|
for(auto& thread : mThreads)
|
|
@@ -142,7 +132,7 @@ namespace BansheeEngine
|
|
|
mThreads.clear();
|
|
mThreads.clear();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void ThreadPool::clearUnused()
|
|
|
|
|
|
|
+ void ThreadPoolBase::clearUnused()
|
|
|
{
|
|
{
|
|
|
CM_LOCK_MUTEX(mMutex);
|
|
CM_LOCK_MUTEX(mMutex);
|
|
|
mAge = 0;
|
|
mAge = 0;
|
|
@@ -188,18 +178,13 @@ namespace BansheeEngine
|
|
|
mThreads.insert(mThreads.end(), activeThreads.begin(), activeThreads.end());
|
|
mThreads.insert(mThreads.end(), activeThreads.begin(), activeThreads.end());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- PooledThread* ThreadPool::createThread()
|
|
|
|
|
- {
|
|
|
|
|
- return cm_new<PooledThread>();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- void ThreadPool::destroyThread(PooledThread* thread)
|
|
|
|
|
|
|
+ void ThreadPoolBase::destroyThread(PooledThread* thread)
|
|
|
{
|
|
{
|
|
|
thread->destroy();
|
|
thread->destroy();
|
|
|
cm_delete(thread);
|
|
cm_delete(thread);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- PooledThread* ThreadPool::getThread()
|
|
|
|
|
|
|
+ PooledThread* ThreadPoolBase::getThread(const String& name)
|
|
|
{
|
|
{
|
|
|
UINT32 age = 0;
|
|
UINT32 age = 0;
|
|
|
{
|
|
{
|
|
@@ -216,7 +201,10 @@ namespace BansheeEngine
|
|
|
for(auto& thread : mThreads)
|
|
for(auto& thread : mThreads)
|
|
|
{
|
|
{
|
|
|
if(thread->isIdle())
|
|
if(thread->isIdle())
|
|
|
|
|
+ {
|
|
|
|
|
+ thread->setName(name);
|
|
|
return thread;
|
|
return thread;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if(newThread == nullptr)
|
|
if(newThread == nullptr)
|
|
@@ -224,14 +212,14 @@ namespace BansheeEngine
|
|
|
if(mThreads.size() >= mMaxCapacity)
|
|
if(mThreads.size() >= mMaxCapacity)
|
|
|
CM_EXCEPT(InvalidStateException, "Unable to create a new thread in the pool because maximum capacity has been reached.");
|
|
CM_EXCEPT(InvalidStateException, "Unable to create a new thread in the pool because maximum capacity has been reached.");
|
|
|
|
|
|
|
|
- newThread = createThread();
|
|
|
|
|
|
|
+ newThread = createThread(name);
|
|
|
mThreads.push_back(newThread);
|
|
mThreads.push_back(newThread);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return newThread;
|
|
return newThread;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- UINT32 ThreadPool::getNumAvailable() const
|
|
|
|
|
|
|
+ UINT32 ThreadPoolBase::getNumAvailable() const
|
|
|
{
|
|
{
|
|
|
UINT32 numAvailable = 0;
|
|
UINT32 numAvailable = 0;
|
|
|
|
|
|
|
@@ -245,7 +233,7 @@ namespace BansheeEngine
|
|
|
return numAvailable;
|
|
return numAvailable;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- UINT32 ThreadPool::getNumActive() const
|
|
|
|
|
|
|
+ UINT32 ThreadPoolBase::getNumActive() const
|
|
|
{
|
|
{
|
|
|
UINT32 numActive = 0;
|
|
UINT32 numActive = 0;
|
|
|
|
|
|
|
@@ -259,7 +247,7 @@ namespace BansheeEngine
|
|
|
return numActive;
|
|
return numActive;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- UINT32 ThreadPool::getNumAllocated() const
|
|
|
|
|
|
|
+ UINT32 ThreadPoolBase::getNumAllocated() const
|
|
|
{
|
|
{
|
|
|
CM_LOCK_MUTEX(mMutex);
|
|
CM_LOCK_MUTEX(mMutex);
|
|
|
|
|
|