diff options
Diffstat (limited to 'indra/llcommon/llworkerthread.cpp')
-rw-r--r-- | indra/llcommon/llworkerthread.cpp | 796 |
1 files changed, 398 insertions, 398 deletions
diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp index 231dbe4310..22a922c94b 100644 --- a/indra/llcommon/llworkerthread.cpp +++ b/indra/llcommon/llworkerthread.cpp @@ -1,398 +1,398 @@ -/** - * @file llworkerthread.cpp - * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" -#include "llworkerthread.h" -#include "llstl.h" - -#if USE_FRAME_CALLBACK_MANAGER -#include "llframecallbackmanager.h" -#endif - -//============================================================================ -// Run on MAIN thread - -LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded, bool should_pause) : - LLQueuedThread(name, threaded, should_pause) -{ - mDeleteMutex = new LLMutex(); - - if(!mLocalAPRFilePoolp) - { - mLocalAPRFilePoolp = new LLVolatileAPRPool() ; - } -} - -LLWorkerThread::~LLWorkerThread() -{ - // Delete any workers in the delete queue (should be safe - had better be!) - if (!mDeleteList.empty()) - { - LL_WARNS() << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size() - << " entries in delete list." << LL_ENDL; - } - - delete mDeleteMutex; - - // ~LLQueuedThread() will be called here -} - -//called only in destructor. -void LLWorkerThread::clearDeleteList() -{ - // Delete any workers in the delete queue (should be safe - had better be!) - if (!mDeleteList.empty()) - { - LL_WARNS() << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size() - << " entries in delete list." << LL_ENDL; - - mDeleteMutex->lock(); - for (LLWorkerClass* worker : mDeleteList) - { - worker->mRequestHandle = LLWorkerThread::nullHandle(); - worker->clearFlags(LLWorkerClass::WCF_HAVE_WORK); - worker->clearFlags(LLWorkerClass::WCF_WORKING); - delete worker; - } - mDeleteList.clear() ; - mDeleteMutex->unlock() ; - } -} - -// virtual -size_t LLWorkerThread::update(F32 max_time_ms) -{ - auto res = LLQueuedThread::update(max_time_ms); - // Delete scheduled workers - std::vector<LLWorkerClass*> delete_list; - std::vector<LLWorkerClass*> abort_list; - mDeleteMutex->lock(); - for (delete_list_t::iterator iter = mDeleteList.begin(); - iter != mDeleteList.end(); ) - { - delete_list_t::iterator curiter = iter++; - LLWorkerClass* worker = *curiter; - if (worker->deleteOK()) - { - if (worker->getFlags(LLWorkerClass::WCF_WORK_FINISHED)) - { - worker->setFlags(LLWorkerClass::WCF_DELETE_REQUESTED); - delete_list.push_back(worker); - mDeleteList.erase(curiter); - } - else if (!worker->getFlags(LLWorkerClass::WCF_ABORT_REQUESTED)) - { - abort_list.push_back(worker); - } - } - } - mDeleteMutex->unlock(); - // abort and delete after releasing mutex - for (LLWorkerClass* worker : abort_list) - { - worker->abortWork(false); - } - for (LLWorkerClass* worker : delete_list) - { - if (worker->mRequestHandle) - { - // Finished but not completed - completeRequest(worker->mRequestHandle); - worker->mRequestHandle = LLWorkerThread::nullHandle(); - worker->clearFlags(LLWorkerClass::WCF_HAVE_WORK); - } - delete worker; - } - // delete and aborted entries mean there's still work to do - res += delete_list.size() + abort_list.size(); - return res; -} - -//---------------------------------------------------------------------------- - -LLWorkerThread::handle_t LLWorkerThread::addWorkRequest(LLWorkerClass* workerclass, S32 param) -{ - handle_t handle = generateHandle(); - - WorkRequest* req = new WorkRequest(handle, workerclass, param); - - bool res = addRequest(req); - if (!res) - { - LL_ERRS() << "add called after LLWorkerThread::cleanupClass()" << LL_ENDL; - req->deleteRequest(); - handle = nullHandle(); - } - - return handle; -} - -void LLWorkerThread::deleteWorker(LLWorkerClass* workerclass) -{ - mDeleteMutex->lock(); - mDeleteList.push_back(workerclass); - mDeleteMutex->unlock(); -} - -//============================================================================ -// Runs on its OWN thread - -LLWorkerThread::WorkRequest::WorkRequest(handle_t handle, LLWorkerClass* workerclass, S32 param) : - LLQueuedThread::QueuedRequest(handle), - mWorkerClass(workerclass), - mParam(param) -{ -} - -LLWorkerThread::WorkRequest::~WorkRequest() -{ -} - -// virtual (required for access by LLWorkerThread) -void LLWorkerThread::WorkRequest::deleteRequest() -{ - LLQueuedThread::QueuedRequest::deleteRequest(); -} - -// virtual -bool LLWorkerThread::WorkRequest::processRequest() -{ - LL_PROFILE_ZONE_SCOPED; - LLWorkerClass* workerclass = getWorkerClass(); - workerclass->setWorking(true); - bool complete = workerclass->doWork(getParam()); - workerclass->setWorking(false); - return complete; -} - -// virtual -void LLWorkerThread::WorkRequest::finishRequest(bool completed) -{ - LL_PROFILE_ZONE_SCOPED; - LLWorkerClass* workerclass = getWorkerClass(); - workerclass->finishWork(getParam(), completed); - U32 flags = LLWorkerClass::WCF_WORK_FINISHED | (completed ? 0 : LLWorkerClass::WCF_WORK_ABORTED); - workerclass->setFlags(flags); -} - -//============================================================================ -// LLWorkerClass:: operates in main thread - -LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& name) - : mWorkerThread(workerthread), - mWorkerClassName(name), - mRequestHandle(LLWorkerThread::nullHandle()), - mMutex(), - mWorkFlags(0) -{ - if (!mWorkerThread) - { - LL_ERRS() << "LLWorkerClass() called with NULL workerthread: " << name << LL_ENDL; - } -} - -LLWorkerClass::~LLWorkerClass() -{ - llassert_always(!(mWorkFlags & WCF_WORKING)); - llassert_always(mWorkFlags & WCF_DELETE_REQUESTED); - llassert_always(!mMutex.isLocked()); - if (mRequestHandle != LLWorkerThread::nullHandle()) - { - LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle); - if (!workreq) - { - LL_ERRS() << "LLWorkerClass destroyed with stale work handle" << LL_ENDL; - } - if (workreq->getStatus() != LLWorkerThread::STATUS_ABORTED && - workreq->getStatus() != LLWorkerThread::STATUS_COMPLETE) - { - LL_ERRS() << "LLWorkerClass destroyed with active worker! Worker Status: " << workreq->getStatus() << LL_ENDL; - } - } -} - -void LLWorkerClass::setWorkerThread(LLWorkerThread* workerthread) -{ - mMutex.lock(); - if (mRequestHandle != LLWorkerThread::nullHandle()) - { - LL_ERRS() << "LLWorkerClass attempt to change WorkerThread with active worker!" << LL_ENDL; - } - mWorkerThread = workerthread; - mMutex.unlock(); -} - -//---------------------------------------------------------------------------- - -//virtual -void LLWorkerClass::finishWork(S32 param, bool success) -{ -} - -//virtual -bool LLWorkerClass::deleteOK() -{ - return true; // default always OK -} - -//---------------------------------------------------------------------------- - -// Called from worker thread -void LLWorkerClass::setWorking(bool working) -{ - mMutex.lock(); - if (working) - { - llassert_always(!(mWorkFlags & WCF_WORKING)); - setFlags(WCF_WORKING); - } - else - { - llassert_always((mWorkFlags & WCF_WORKING)); - clearFlags(WCF_WORKING); - } - mMutex.unlock(); -} - -//---------------------------------------------------------------------------- - -bool LLWorkerClass::yield() -{ - LLThread::yield(); - mWorkerThread->checkPause(); - bool res; - mMutex.lock(); - res = (getFlags() & WCF_ABORT_REQUESTED) != 0; - mMutex.unlock(); - return res; -} - -//---------------------------------------------------------------------------- - -// calls startWork, adds doWork() to queue -void LLWorkerClass::addWork(S32 param) -{ - mMutex.lock(); - llassert_always(!(mWorkFlags & (WCF_WORKING|WCF_HAVE_WORK))); - if (mRequestHandle != LLWorkerThread::nullHandle()) - { - LL_ERRS() << "LLWorkerClass attempt to add work with active worker!" << LL_ENDL; - } -#if _DEBUG -// LL_INFOS() << "addWork: " << mWorkerClassName << " Param: " << param << LL_ENDL; -#endif - startWork(param); - clearFlags(WCF_WORK_FINISHED|WCF_WORK_ABORTED); - setFlags(WCF_HAVE_WORK); - mRequestHandle = mWorkerThread->addWorkRequest(this, param); - mMutex.unlock(); -} - -void LLWorkerClass::abortWork(bool autocomplete) -{ - mMutex.lock(); -#if _DEBUG -// LLWorkerThread::WorkRequest* workreq = mWorkerThread->getRequest(mRequestHandle); -// if (workreq) -// LL_INFOS() << "abortWork: " << mWorkerClassName << " Param: " << workreq->getParam() << LL_ENDL; -#endif - if (mRequestHandle != LLWorkerThread::nullHandle()) - { - mWorkerThread->abortRequest(mRequestHandle, autocomplete); - setFlags(WCF_ABORT_REQUESTED); - } - mMutex.unlock(); -} - -// if doWork is complete or aborted, call endWork() and return true -bool LLWorkerClass::checkWork(bool aborting) -{ - LLMutexLock lock(&mMutex); - bool complete = false, abort = false; - if (mRequestHandle != LLWorkerThread::nullHandle()) - { - LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle); - if(!workreq) - { - if(mWorkerThread->isQuitting() || mWorkerThread->isStopped()) //the mWorkerThread is not running - { - mRequestHandle = LLWorkerThread::nullHandle(); - clearFlags(WCF_HAVE_WORK); - } - else - { - llassert_always(workreq); - } - return true ; - } - - LLQueuedThread::status_t status = workreq->getStatus(); - if (status == LLWorkerThread::STATUS_ABORTED) - { - complete = true; - abort = true; - } - else if (status == LLWorkerThread::STATUS_COMPLETE) - { - complete = true; - } - else - { - llassert_always(!aborting || (workreq->getFlags() & LLQueuedThread::FLAG_ABORT)); - } - if (complete) - { - llassert_always(!(getFlags(WCF_WORKING))); - endWork(workreq->getParam(), abort); - mWorkerThread->completeRequest(mRequestHandle); - mRequestHandle = LLWorkerThread::nullHandle(); - clearFlags(WCF_HAVE_WORK); - } - } - else - { - complete = true; - } - return complete; -} - -void LLWorkerClass::scheduleDelete() -{ - bool do_delete = false; - mMutex.lock(); - if (!(getFlags(WCF_DELETE_REQUESTED))) - { - setFlags(WCF_DELETE_REQUESTED); - do_delete = true; - } - mMutex.unlock(); - if (do_delete) - { - mWorkerThread->deleteWorker(this); - } -} - -//============================================================================ - +/**
+ * @file llworkerthread.cpp
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llworkerthread.h"
+#include "llstl.h"
+
+#if USE_FRAME_CALLBACK_MANAGER
+#include "llframecallbackmanager.h"
+#endif
+
+//============================================================================
+// Run on MAIN thread
+
+LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded, bool should_pause) :
+ LLQueuedThread(name, threaded, should_pause)
+{
+ mDeleteMutex = new LLMutex();
+
+ if(!mLocalAPRFilePoolp)
+ {
+ mLocalAPRFilePoolp = new LLVolatileAPRPool() ;
+ }
+}
+
+LLWorkerThread::~LLWorkerThread()
+{
+ // Delete any workers in the delete queue (should be safe - had better be!)
+ if (!mDeleteList.empty())
+ {
+ LL_WARNS() << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size()
+ << " entries in delete list." << LL_ENDL;
+ }
+
+ delete mDeleteMutex;
+
+ // ~LLQueuedThread() will be called here
+}
+
+//called only in destructor.
+void LLWorkerThread::clearDeleteList()
+{
+ // Delete any workers in the delete queue (should be safe - had better be!)
+ if (!mDeleteList.empty())
+ {
+ LL_WARNS() << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size()
+ << " entries in delete list." << LL_ENDL;
+
+ mDeleteMutex->lock();
+ for (LLWorkerClass* worker : mDeleteList)
+ {
+ worker->mRequestHandle = LLWorkerThread::nullHandle();
+ worker->clearFlags(LLWorkerClass::WCF_HAVE_WORK);
+ worker->clearFlags(LLWorkerClass::WCF_WORKING);
+ delete worker;
+ }
+ mDeleteList.clear() ;
+ mDeleteMutex->unlock() ;
+ }
+}
+
+// virtual
+size_t LLWorkerThread::update(F32 max_time_ms)
+{
+ auto res = LLQueuedThread::update(max_time_ms);
+ // Delete scheduled workers
+ std::vector<LLWorkerClass*> delete_list;
+ std::vector<LLWorkerClass*> abort_list;
+ mDeleteMutex->lock();
+ for (delete_list_t::iterator iter = mDeleteList.begin();
+ iter != mDeleteList.end(); )
+ {
+ delete_list_t::iterator curiter = iter++;
+ LLWorkerClass* worker = *curiter;
+ if (worker->deleteOK())
+ {
+ if (worker->getFlags(LLWorkerClass::WCF_WORK_FINISHED))
+ {
+ worker->setFlags(LLWorkerClass::WCF_DELETE_REQUESTED);
+ delete_list.push_back(worker);
+ mDeleteList.erase(curiter);
+ }
+ else if (!worker->getFlags(LLWorkerClass::WCF_ABORT_REQUESTED))
+ {
+ abort_list.push_back(worker);
+ }
+ }
+ }
+ mDeleteMutex->unlock();
+ // abort and delete after releasing mutex
+ for (LLWorkerClass* worker : abort_list)
+ {
+ worker->abortWork(false);
+ }
+ for (LLWorkerClass* worker : delete_list)
+ {
+ if (worker->mRequestHandle)
+ {
+ // Finished but not completed
+ completeRequest(worker->mRequestHandle);
+ worker->mRequestHandle = LLWorkerThread::nullHandle();
+ worker->clearFlags(LLWorkerClass::WCF_HAVE_WORK);
+ }
+ delete worker;
+ }
+ // delete and aborted entries mean there's still work to do
+ res += delete_list.size() + abort_list.size();
+ return res;
+}
+
+//----------------------------------------------------------------------------
+
+LLWorkerThread::handle_t LLWorkerThread::addWorkRequest(LLWorkerClass* workerclass, S32 param)
+{
+ handle_t handle = generateHandle();
+
+ WorkRequest* req = new WorkRequest(handle, workerclass, param);
+
+ bool res = addRequest(req);
+ if (!res)
+ {
+ LL_ERRS() << "add called after LLWorkerThread::cleanupClass()" << LL_ENDL;
+ req->deleteRequest();
+ handle = nullHandle();
+ }
+
+ return handle;
+}
+
+void LLWorkerThread::deleteWorker(LLWorkerClass* workerclass)
+{
+ mDeleteMutex->lock();
+ mDeleteList.push_back(workerclass);
+ mDeleteMutex->unlock();
+}
+
+//============================================================================
+// Runs on its OWN thread
+
+LLWorkerThread::WorkRequest::WorkRequest(handle_t handle, LLWorkerClass* workerclass, S32 param) :
+ LLQueuedThread::QueuedRequest(handle),
+ mWorkerClass(workerclass),
+ mParam(param)
+{
+}
+
+LLWorkerThread::WorkRequest::~WorkRequest()
+{
+}
+
+// virtual (required for access by LLWorkerThread)
+void LLWorkerThread::WorkRequest::deleteRequest()
+{
+ LLQueuedThread::QueuedRequest::deleteRequest();
+}
+
+// virtual
+bool LLWorkerThread::WorkRequest::processRequest()
+{
+ LL_PROFILE_ZONE_SCOPED;
+ LLWorkerClass* workerclass = getWorkerClass();
+ workerclass->setWorking(true);
+ bool complete = workerclass->doWork(getParam());
+ workerclass->setWorking(false);
+ return complete;
+}
+
+// virtual
+void LLWorkerThread::WorkRequest::finishRequest(bool completed)
+{
+ LL_PROFILE_ZONE_SCOPED;
+ LLWorkerClass* workerclass = getWorkerClass();
+ workerclass->finishWork(getParam(), completed);
+ U32 flags = LLWorkerClass::WCF_WORK_FINISHED | (completed ? 0 : LLWorkerClass::WCF_WORK_ABORTED);
+ workerclass->setFlags(flags);
+}
+
+//============================================================================
+// LLWorkerClass:: operates in main thread
+
+LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& name)
+ : mWorkerThread(workerthread),
+ mWorkerClassName(name),
+ mRequestHandle(LLWorkerThread::nullHandle()),
+ mMutex(),
+ mWorkFlags(0)
+{
+ if (!mWorkerThread)
+ {
+ LL_ERRS() << "LLWorkerClass() called with NULL workerthread: " << name << LL_ENDL;
+ }
+}
+
+LLWorkerClass::~LLWorkerClass()
+{
+ llassert_always(!(mWorkFlags & WCF_WORKING));
+ llassert_always(mWorkFlags & WCF_DELETE_REQUESTED);
+ llassert_always(!mMutex.isLocked());
+ if (mRequestHandle != LLWorkerThread::nullHandle())
+ {
+ LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle);
+ if (!workreq)
+ {
+ LL_ERRS() << "LLWorkerClass destroyed with stale work handle" << LL_ENDL;
+ }
+ if (workreq->getStatus() != LLWorkerThread::STATUS_ABORTED &&
+ workreq->getStatus() != LLWorkerThread::STATUS_COMPLETE)
+ {
+ LL_ERRS() << "LLWorkerClass destroyed with active worker! Worker Status: " << workreq->getStatus() << LL_ENDL;
+ }
+ }
+}
+
+void LLWorkerClass::setWorkerThread(LLWorkerThread* workerthread)
+{
+ mMutex.lock();
+ if (mRequestHandle != LLWorkerThread::nullHandle())
+ {
+ LL_ERRS() << "LLWorkerClass attempt to change WorkerThread with active worker!" << LL_ENDL;
+ }
+ mWorkerThread = workerthread;
+ mMutex.unlock();
+}
+
+//----------------------------------------------------------------------------
+
+//virtual
+void LLWorkerClass::finishWork(S32 param, bool success)
+{
+}
+
+//virtual
+bool LLWorkerClass::deleteOK()
+{
+ return true; // default always OK
+}
+
+//----------------------------------------------------------------------------
+
+// Called from worker thread
+void LLWorkerClass::setWorking(bool working)
+{
+ mMutex.lock();
+ if (working)
+ {
+ llassert_always(!(mWorkFlags & WCF_WORKING));
+ setFlags(WCF_WORKING);
+ }
+ else
+ {
+ llassert_always((mWorkFlags & WCF_WORKING));
+ clearFlags(WCF_WORKING);
+ }
+ mMutex.unlock();
+}
+
+//----------------------------------------------------------------------------
+
+bool LLWorkerClass::yield()
+{
+ LLThread::yield();
+ mWorkerThread->checkPause();
+ bool res;
+ mMutex.lock();
+ res = (getFlags() & WCF_ABORT_REQUESTED) != 0;
+ mMutex.unlock();
+ return res;
+}
+
+//----------------------------------------------------------------------------
+
+// calls startWork, adds doWork() to queue
+void LLWorkerClass::addWork(S32 param)
+{
+ mMutex.lock();
+ llassert_always(!(mWorkFlags & (WCF_WORKING|WCF_HAVE_WORK)));
+ if (mRequestHandle != LLWorkerThread::nullHandle())
+ {
+ LL_ERRS() << "LLWorkerClass attempt to add work with active worker!" << LL_ENDL;
+ }
+#if _DEBUG
+// LL_INFOS() << "addWork: " << mWorkerClassName << " Param: " << param << LL_ENDL;
+#endif
+ startWork(param);
+ clearFlags(WCF_WORK_FINISHED|WCF_WORK_ABORTED);
+ setFlags(WCF_HAVE_WORK);
+ mRequestHandle = mWorkerThread->addWorkRequest(this, param);
+ mMutex.unlock();
+}
+
+void LLWorkerClass::abortWork(bool autocomplete)
+{
+ mMutex.lock();
+#if _DEBUG
+// LLWorkerThread::WorkRequest* workreq = mWorkerThread->getRequest(mRequestHandle);
+// if (workreq)
+// LL_INFOS() << "abortWork: " << mWorkerClassName << " Param: " << workreq->getParam() << LL_ENDL;
+#endif
+ if (mRequestHandle != LLWorkerThread::nullHandle())
+ {
+ mWorkerThread->abortRequest(mRequestHandle, autocomplete);
+ setFlags(WCF_ABORT_REQUESTED);
+ }
+ mMutex.unlock();
+}
+
+// if doWork is complete or aborted, call endWork() and return true
+bool LLWorkerClass::checkWork(bool aborting)
+{
+ LLMutexLock lock(&mMutex);
+ bool complete = false, abort = false;
+ if (mRequestHandle != LLWorkerThread::nullHandle())
+ {
+ LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle);
+ if(!workreq)
+ {
+ if(mWorkerThread->isQuitting() || mWorkerThread->isStopped()) //the mWorkerThread is not running
+ {
+ mRequestHandle = LLWorkerThread::nullHandle();
+ clearFlags(WCF_HAVE_WORK);
+ }
+ else
+ {
+ llassert_always(workreq);
+ }
+ return true ;
+ }
+
+ LLQueuedThread::status_t status = workreq->getStatus();
+ if (status == LLWorkerThread::STATUS_ABORTED)
+ {
+ complete = true;
+ abort = true;
+ }
+ else if (status == LLWorkerThread::STATUS_COMPLETE)
+ {
+ complete = true;
+ }
+ else
+ {
+ llassert_always(!aborting || (workreq->getFlags() & LLQueuedThread::FLAG_ABORT));
+ }
+ if (complete)
+ {
+ llassert_always(!(getFlags(WCF_WORKING)));
+ endWork(workreq->getParam(), abort);
+ mWorkerThread->completeRequest(mRequestHandle);
+ mRequestHandle = LLWorkerThread::nullHandle();
+ clearFlags(WCF_HAVE_WORK);
+ }
+ }
+ else
+ {
+ complete = true;
+ }
+ return complete;
+}
+
+void LLWorkerClass::scheduleDelete()
+{
+ bool do_delete = false;
+ mMutex.lock();
+ if (!(getFlags(WCF_DELETE_REQUESTED)))
+ {
+ setFlags(WCF_DELETE_REQUESTED);
+ do_delete = true;
+ }
+ mMutex.unlock();
+ if (do_delete)
+ {
+ mWorkerThread->deleteWorker(this);
+ }
+}
+
+//============================================================================
+
|