From 2f8be401cc4fdf6cb8be02a60aa781029264e0d1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 29 Mar 2016 00:25:51 +0200 Subject: [PATCH] Add the unref work items to the front of the workqueue (Bug #3273) Ensures that memory still gets freed even if the workqueue is overloaded. --- apps/openmw/mwworld/cellpreloader.cpp | 2 +- components/sceneutil/unrefqueue.cpp | 2 +- components/sceneutil/workqueue.cpp | 11 +++++++---- components/sceneutil/workqueue.hpp | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwworld/cellpreloader.cpp b/apps/openmw/mwworld/cellpreloader.cpp index f2881d68f..349bc081f 100644 --- a/apps/openmw/mwworld/cellpreloader.cpp +++ b/apps/openmw/mwworld/cellpreloader.cpp @@ -238,7 +238,7 @@ namespace MWWorld } // the resource cache is cleared from the worker thread so that we're not holding up the main thread with delete operations - mWorkQueue->addWorkItem(new UpdateCacheItem(mResourceSystem, mTerrain, timestamp)); + mWorkQueue->addWorkItem(new UpdateCacheItem(mResourceSystem, mTerrain, timestamp), true); } void CellPreloader::setExpiryDelay(double expiryDelay) diff --git a/components/sceneutil/unrefqueue.cpp b/components/sceneutil/unrefqueue.cpp index a5eb1654e..10d568298 100644 --- a/components/sceneutil/unrefqueue.cpp +++ b/components/sceneutil/unrefqueue.cpp @@ -40,7 +40,7 @@ namespace SceneUtil if (mWorkItem->mObjects.empty()) return; - workQueue->addWorkItem(mWorkItem); + workQueue->addWorkItem(mWorkItem, true); mWorkItem = new UnrefWorkItem; } diff --git a/components/sceneutil/workqueue.cpp b/components/sceneutil/workqueue.cpp index bbd9f4840..0685493d0 100644 --- a/components/sceneutil/workqueue.cpp +++ b/components/sceneutil/workqueue.cpp @@ -55,7 +55,7 @@ WorkQueue::~WorkQueue() { OpenThreads::ScopedLock lock(mMutex); while (!mQueue.empty()) - mQueue.pop(); + mQueue.pop_back(); mIsReleased = true; mCondition.broadcast(); } @@ -67,7 +67,7 @@ WorkQueue::~WorkQueue() } } -void WorkQueue::addWorkItem(osg::ref_ptr item) +void WorkQueue::addWorkItem(osg::ref_ptr item, bool front) { if (item->isDone()) { @@ -76,7 +76,10 @@ void WorkQueue::addWorkItem(osg::ref_ptr item) } OpenThreads::ScopedLock lock(mMutex); - mQueue.push(item); + if (front) + mQueue.push_front(item); + else + mQueue.push_back(item); mCondition.signal(); } @@ -90,7 +93,7 @@ osg::ref_ptr WorkQueue::removeWorkItem() if (!mQueue.empty()) { osg::ref_ptr item = mQueue.front(); - mQueue.pop(); + mQueue.pop_front(); return item; } else diff --git a/components/sceneutil/workqueue.hpp b/components/sceneutil/workqueue.hpp index bc2e55647..e7b0151dd 100644 --- a/components/sceneutil/workqueue.hpp +++ b/components/sceneutil/workqueue.hpp @@ -50,7 +50,8 @@ namespace SceneUtil /// Add a new work item to the back of the queue. /// @par The work item's waitTillDone() method may be used by the caller to wait until the work is complete. - void addWorkItem(osg::ref_ptr item); + /// @param front If true, add item to the front of the queue. If false (default), add to the back. + void addWorkItem(osg::ref_ptr item, bool front=false); /// Get the next work item from the front of the queue. If the queue is empty, waits until a new item is added. /// If the workqueue is in the process of being destroyed, may return NULL. @@ -59,7 +60,7 @@ namespace SceneUtil private: bool mIsReleased; - std::queue > mQueue; + std::deque > mQueue; OpenThreads::Mutex mMutex; OpenThreads::Condition mCondition;