You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw-tes3mp/components/sceneutil/workqueue.cpp

123 lines
2.2 KiB
C++

#include "workqueue.hpp"
namespace SceneUtil
{
void WorkTicket::waitTillDone()
{
if (mDone > 0)
return;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
while (mDone == 0)
{
mCondition.wait(&mMutex);
}
}
void WorkTicket::signalDone()
{
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
mDone.exchange(1);
}
mCondition.broadcast();
}
WorkItem::WorkItem()
: mTicket(new WorkTicket)
{
mTicket->setThreadSafeRefUnref(true);
}
WorkItem::~WorkItem()
{
}
void WorkItem::doWork()
{
mTicket->signalDone();
}
osg::ref_ptr<WorkTicket> WorkItem::getTicket()
{
return mTicket;
}
WorkQueue::WorkQueue(int workerThreads)
: mIsReleased(false)
{
for (int i=0; i<workerThreads; ++i)
{
WorkThread* thread = new WorkThread(this);
mThreads.push_back(thread);
thread->startThread();
}
}
WorkQueue::~WorkQueue()
{
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
while (mQueue.size())
{
WorkItem* item = mQueue.front();
delete item;
mQueue.pop();
}
mIsReleased = true;
mCondition.broadcast();
}
for (unsigned int i=0; i<mThreads.size(); ++i)
{
mThreads[i]->join();
delete mThreads[i];
}
}
osg::ref_ptr<WorkTicket> WorkQueue::addWorkItem(WorkItem *item)
{
osg::ref_ptr<WorkTicket> ticket = item->getTicket();
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
mQueue.push(item);
mCondition.signal();
return ticket;
}
WorkItem *WorkQueue::removeWorkItem()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mMutex);
while (!mQueue.size() && !mIsReleased)
{
mCondition.wait(&mMutex);
}
if (mQueue.size())
{
WorkItem* item = mQueue.front();
mQueue.pop();
return item;
}
else
return NULL;
}
WorkThread::WorkThread(WorkQueue *workQueue)
: mWorkQueue(workQueue)
{
}
void WorkThread::run()
{
while (true)
{
WorkItem* item = mWorkQueue->removeWorkItem();
if (!item)
return;
item->doWork();
delete item;
}
}
}