mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 07:26:39 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			122 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			122 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;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
}
 |