#include "workqueue.hpp" #include namespace SceneUtil { void WorkItem::waitTillDone() { if (mDone > 0) return; OpenThreads::ScopedLock lock(mMutex); while (mDone == 0) { mCondition.wait(&mMutex); } } void WorkItem::signalDone() { { OpenThreads::ScopedLock lock(mMutex); mDone.exchange(1); } mCondition.broadcast(); } WorkItem::WorkItem() { } WorkItem::~WorkItem() { } bool WorkItem::isDone() const { return (mDone > 0); } WorkQueue::WorkQueue(int workerThreads) : mIsReleased(false) { for (int i=0; istartThread(); } } WorkQueue::~WorkQueue() { { OpenThreads::ScopedLock lock(mMutex); while (!mQueue.empty()) mQueue.pop_back(); mIsReleased = true; mCondition.broadcast(); } for (unsigned int i=0; ijoin(); delete mThreads[i]; } } void WorkQueue::addWorkItem(osg::ref_ptr item, bool front) { if (item->isDone()) { std::cerr << "Error: trying to add a work item that is already completed" << std::endl; return; } OpenThreads::ScopedLock lock(mMutex); if (front) mQueue.push_front(item); else mQueue.push_back(item); mCondition.signal(); } osg::ref_ptr WorkQueue::removeWorkItem() { OpenThreads::ScopedLock lock(mMutex); while (mQueue.empty() && !mIsReleased) { mCondition.wait(&mMutex); } if (!mQueue.empty()) { osg::ref_ptr item = mQueue.front(); mQueue.pop_front(); return item; } else return NULL; } unsigned int WorkQueue::getNumItems() const { OpenThreads::ScopedLock lock(mMutex); return mQueue.size(); } unsigned int WorkQueue::getNumActiveThreads() const { unsigned int count = 0; for (unsigned int i=0; iisActive()) ++count; } return count; } WorkThread::WorkThread(WorkQueue *workQueue) : mWorkQueue(workQueue) , mActive(false) { } void WorkThread::run() { while (true) { osg::ref_ptr item = mWorkQueue->removeWorkItem(); if (!item) return; mActive = true; item->doWork(); item->signalDone(); mActive = false; } } bool WorkThread::isActive() const { return mActive; } }