diff options
author | Rider Linden <rider@lindenlab.com> | 2015-06-23 11:58:15 -0700 |
---|---|---|
committer | Rider Linden <rider@lindenlab.com> | 2015-06-23 11:58:15 -0700 |
commit | ed4099628c362cdc880962198a2a4984ab67dd8f (patch) | |
tree | 693d13a10eec3bd4c34b532772a130647e08ca94 | |
parent | 1060094eec34dfd355e2995409cf37f3a84240d0 (diff) |
Start work on coprocedure manager.
-rwxr-xr-x | indra/newview/CMakeLists.txt | 2 | ||||
-rwxr-xr-x | indra/newview/llassetuploadresponders.cpp | 3 | ||||
-rwxr-xr-x | indra/newview/llassetuploadresponders.h | 2 | ||||
-rw-r--r-- | indra/newview/llcoproceduremanager.cpp | 177 | ||||
-rw-r--r-- | indra/newview/llcoproceduremanager.h | 118 |
5 files changed, 301 insertions, 1 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 51787b6258..9b3324700a 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -164,6 +164,7 @@ set(viewer_SOURCE_FILES llconversationloglistitem.cpp llconversationmodel.cpp llconversationview.cpp + llcoproceduremanager.cpp llcurrencyuimanager.cpp llcylinder.cpp lldateutil.cpp @@ -764,6 +765,7 @@ set(viewer_HEADER_FILES llconversationloglistitem.h llconversationmodel.h llconversationview.h + llcoproceduremanager.h llcurrencyuimanager.h llcylinder.h lldateutil.h diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index d2b1dcbf35..e492b8cf5d 100755 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -674,6 +674,7 @@ void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content) } +#if 0 ///////////////////////////////////////////////////// // LLNewAgentInventoryVariablePriceResponder::Impl // ///////////////////////////////////////////////////// @@ -1144,5 +1145,5 @@ void LLNewAgentInventoryVariablePriceResponder::showConfirmationDialog( LLPointer<LLNewAgentInventoryVariablePriceResponder>(this))); } } - +#endif diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index 7fbebc7481..18968bb1af 100755 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -79,6 +79,7 @@ protected: virtual void httpFailure(); }; +#if 0 // A base class which goes through and performs some default // actions for variable price uploads. If more specific actions // are needed (such as different confirmation messages, etc.) @@ -115,6 +116,7 @@ private: class Impl; Impl* mImpl; }; +#endif class LLUpdateAgentInventoryResponder : public LLAssetUploadResponder { diff --git a/indra/newview/llcoproceduremanager.cpp b/indra/newview/llcoproceduremanager.cpp new file mode 100644 index 0000000000..3f5fe7a582 --- /dev/null +++ b/indra/newview/llcoproceduremanager.cpp @@ -0,0 +1,177 @@ +/** +* @file llupdloadmanager.cpp +* @author Rider Linden +* @brief Singleton class for managing asset uploads to the sim. +* +* $LicenseInfo:firstyear=2015&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2015, 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 "llviewerprecompiledheaders.h" +#include "linden_common.h" + +#include "llviewercontrol.h" + +#include "llcoproceduremanager.h" + +//========================================================================= +#define COROCOUNT 1 + +//========================================================================= +LLCoprocedureManager::LLCoprocedureManager(): + LLSingleton<LLCoprocedureManager>(), + mPendingCoprocs(), + mShutdown(false), + mWakeupTrigger("CoprocedureManager", true), + mCoroMapping(), + mHTTPPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID) +{ + initializeManager(); +} + +LLCoprocedureManager::~LLCoprocedureManager() +{ + shutdown(); +} + +//========================================================================= +void LLCoprocedureManager::initializeManager() +{ + mShutdown = false; + + // *TODO: Retrieve the actual number of concurrent coroutines fro gSavedSettings and + // clamp to a "reasonable" number. + for (int count = 0; count < COROCOUNT; ++count) + { + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter = + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t( + new LLCoreHttpUtil::HttpCoroutineAdapter("uploadPostAdapter", mHTTPPolicy)); + + std::string uploadCoro = LLCoros::instance().launch("LLCoprocedureManager::coprocedureInvokerCoro", + boost::bind(&LLCoprocedureManager::coprocedureInvokerCoro, this, _1, httpAdapter)); + + mCoroMapping.insert(CoroAdapterMap_t::value_type(uploadCoro, httpAdapter)); + } + + mWakeupTrigger.post(LLSD()); +} + +void LLCoprocedureManager::shutdown(bool hardShutdown) +{ + CoroAdapterMap_t::iterator it; + + for (it = mCoroMapping.begin(); it != mCoroMapping.end(); ++it) + { + if (!(*it).first.empty()) + { + if (hardShutdown) + { + LLCoros::instance().kill((*it).first); + } + } + if ((*it).second) + { + (*it).second->cancelYieldingOperation(); + } + } + + mShutdown = true; + mCoroMapping.clear(); + mPendingCoprocs.clear(); +} + +//========================================================================= +LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &name, LLCoprocedureManager::CoProcedure_t proc) +{ + LLUUID id(LLUUID::generateNewID()); + + mPendingCoprocs.push_back(QueuedCoproc::ptr_t(new QueuedCoproc(name, id, proc))); + LL_INFOS() << "Coprocedure(" << name << ") enqueued with id=" << id.asString() << LL_ENDL; + + mWakeupTrigger.post(LLSD()); + + return id; +} + +void LLCoprocedureManager::cancelCoprocedure(const LLUUID &id) +{ + // first check the active coroutines. If there, remove it and return. + ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(id); + if (itActive != mActiveCoprocs.end()) + { + LL_INFOS() << "Found and canceling active coprocedure with id=" << id.asString() << LL_ENDL; + (*itActive).second->cancelYieldingOperation(); + mActiveCoprocs.erase(itActive); + return; + } + + for (AssetQueue_t::iterator it = mPendingCoprocs.begin(); it != mPendingCoprocs.end(); ++it) + { + if ((*it)->mId == id) + { + LL_INFOS() << "Found and removing queued coroutine(" << (*it)->mName << ") with Id=" << id.asString() << LL_ENDL; + mPendingCoprocs.erase(it); + return; + } + } + + LL_INFOS() << "Coprocedure with Id=" << id.asString() << " was not found." << LL_ENDL; +} + +//========================================================================= +void LLCoprocedureManager::coprocedureInvokerCoro(LLCoros::self& self, LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter) +{ + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + while (!mShutdown) + { + waitForEventOn(self, mWakeupTrigger); + if (mShutdown) + break; + + while (!mPendingCoprocs.empty()) + { + QueuedCoproc::ptr_t coproc = mPendingCoprocs.front(); + mPendingCoprocs.pop_front(); + mActiveCoprocs.insert(ActiveCoproc_t::value_type(coproc->mId, httpAdapter)); + + LL_INFOS() << "Dequeued and invoking coprocedure(" << coproc->mName << ") with id=" << coproc->mId.asString() << LL_ENDL; + + try + { + coproc->mProc(self, httpAdapter, coproc->mId); + } + catch (std::exception &e) + { + LL_WARNS() << "Coprocedure(" << coproc->mName << ") id=" << coproc->mId.asString() << + " threw an exception! Message=\"" << e.what() << "\"" << LL_ENDL; + } + + LL_INFOS() << "Finished coprocedure(" << coproc->mName << ")" << LL_ENDL; + + ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(coproc->mId); + if (itActive != mActiveCoprocs.end()) + { + mActiveCoprocs.erase(itActive); + } + } + } +} diff --git a/indra/newview/llcoproceduremanager.h b/indra/newview/llcoproceduremanager.h new file mode 100644 index 0000000000..8902b217c2 --- /dev/null +++ b/indra/newview/llcoproceduremanager.h @@ -0,0 +1,118 @@ +/** +* @file llupdloadmanager.h +* @author Rider Linden +* @brief Singleton class for managing asset uploads to the sim. +* +* $LicenseInfo:firstyear=2015&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2015, 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$ +*/ + +#ifndef LL_UPLOAD_MANAGER_H +#define LL_UPLOAD_MANAGER_H + +#include "lleventcoro.h" +#include "llcoros.h" +#include "llcorehttputil.h" +#include "lluuid.h" + +class LLCoprocedureManager : public LLSingleton < LLCoprocedureManager > +{ +public: + typedef boost::function<void(LLCoros::self &, LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, const LLUUID &id)> CoProcedure_t; + + virtual ~LLCoprocedureManager(); + + /// Places the coprocedure on the queue for processing. + /// + /// @param name Is used for debugging and should identify this coroutine. + /// @param proc Is a bound function to be executed + /// + /// @return This method returns a UUID that can be used later to cancel execution. + LLUUID enqueueCoprocedure(const std::string &name, CoProcedure_t proc); + + /// Cancel a coprocedure. If the coprocedure is already being actively executed + /// this method calls cancelYieldingOperation() on the associated HttpAdapter + /// If it has not yet been dequeued it is simply removed from the queue. + void cancelCoprocedure(const LLUUID &id); + + /// Requests a shutdown of the upload manager. Passing 'true' will perform + /// an immediate kill on the upload coroutine. + void shutdown(bool hardShutdown = false); + + /// Returns the number of coprocedures in the queue awaiting processing. + /// + inline size_t countPending() const + { + return mPendingCoprocs.size(); + } + + /// Returns the number of coprocedures actively being processed. + /// + inline size_t countActive() const + { + return mActiveCoprocs.size(); + } + + /// Returns the total number of coprocedures either queued or in active processing. + /// + inline size_t count() const + { + return countPending() + countActive(); + } + +protected: + LLCoprocedureManager(); + +private: + struct QueuedCoproc + { + typedef boost::shared_ptr<QueuedCoproc> ptr_t; + + QueuedCoproc(const std::string &name, const LLUUID &id, CoProcedure_t proc): + mName(name), + mId(id), + mProc(proc) + {} + + std::string mName; + LLUUID mId; + CoProcedure_t mProc; + }; + + typedef std::deque<QueuedCoproc::ptr_t> AssetQueue_t; + typedef std::map<LLUUID, LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t> ActiveCoproc_t; + + AssetQueue_t mPendingCoprocs; + ActiveCoproc_t mActiveCoprocs; + bool mShutdown; + LLEventStream mWakeupTrigger; + + + typedef std::map<std::string, LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t> CoroAdapterMap_t; + LLCore::HttpRequest::policy_t mHTTPPolicy; + + CoroAdapterMap_t mCoroMapping; + + void initializeManager(); + void coprocedureInvokerCoro(LLCoros::self& self, LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter); +}; + +#endif |