From f90023fc0b3b61fd346a2b56e30e5f3c35814192 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 2 Jul 2015 17:00:32 -0400 Subject: MAINT-5357: Introduce and populate llcoro:: namespace. To date, the coroutine helper functions in lleventcoro.h have been in the global namespace. Migrate them into llcoro namespace, and fix references. Specifically, LLVoidListener => llcoro::VoidListener, and voidlistener(), postAndWait(), both waitForEventOn(), postAndWait2(), errorException() and errorLog() have been moved into llcoro. Also migrate new LLCoros::get_self() and Suspending to llcoro:: namespace. While at it, I realized that -- having converted several lleventcoro.h functions from templates (for arbitrary 'self' parameter type) to ordinary functions, having moved them from lleventcoro.h to lleventcoro.cpp, we can now migrate their helpers from lleventcoro.h to lleventcoro.cpp as well. This eliminates the need for the LLEventDetail namespace; the relevant helpers are now in an anonymous namespace in the .cpp file: listenerNameForCoro(), storeToLLSDPath(), WaitForEventOnHelper and wfeoh(). --- indra/llcommon/llcoros.cpp | 10 +-- indra/llcommon/llcoros.h | 35 +++++---- indra/llcommon/lleventcoro.cpp | 119 ++++++++++++++++++++++++----- indra/llcommon/lleventcoro.h | 122 +++++++----------------------- indra/llcommon/tests/lleventcoro_test.cpp | 5 +- indra/llmessage/llcorehttputil.cpp | 10 +-- indra/newview/llcoproceduremanager.cpp | 2 +- indra/newview/lleventpoll.cpp | 2 +- indra/viewer_components/login/lllogin.cpp | 6 +- 9 files changed, 166 insertions(+), 145 deletions(-) diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 2d0c419ae0..957fe034e1 100755 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -69,9 +69,9 @@ sCurrentSelf(no_cleanup); } // anonymous //static -LLCoros::coro::self& LLCoros::get_self() +LLCoros::coro::self& llcoro::get_self() { - coro::self* current_self = sCurrentSelf.get(); + LLCoros::coro::self* current_self = sCurrentSelf.get(); if (! current_self) { LL_ERRS("LLCoros") << "Calling get_self() from non-coroutine context!" << LL_ENDL; @@ -79,7 +79,7 @@ LLCoros::coro::self& LLCoros::get_self() return *current_self; } -LLCoros::Suspending::Suspending(): +llcoro::Suspending::Suspending(): mSuspended(sCurrentSelf.get()) { // For the duration of our time away from this coroutine, sCurrentSelf @@ -87,7 +87,7 @@ LLCoros::Suspending::Suspending(): sCurrentSelf.reset(); } -LLCoros::Suspending::~Suspending() +llcoro::Suspending::~Suspending() { // Okay, we're back, reinstate previous value of sCurrentSelf. sCurrentSelf.reset(mSuspended); @@ -171,7 +171,7 @@ bool LLCoros::kill(const std::string& name) std::string LLCoros::getName() const { // Walk the existing coroutines, looking for the current one. - void* self_id = get_self().get_id(); + void* self_id = llcoro::get_self().get_id(); for (CoroMap::const_iterator mi(mCoros.begin()), mend(mCoros.end()); mi != mend; ++mi) { namespace coro_private = boost::dcoroutines::detail; diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 3f58a17aa9..e478600f00 100755 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -137,21 +137,6 @@ public: */ std::string getName() const; - /// get the current coro::self& for those who really really care - static coro::self& get_self(); - - /// Instantiate one of these in a block surrounding any leaf point when - /// control literally switches away from this coroutine. - class Suspending - { - public: - Suspending(); - ~Suspending(); - - private: - coro::self* mSuspended; - }; - /// for delayed initialization void setStackSize(S32 stacksize); @@ -166,4 +151,24 @@ private: CoroMap mCoros; }; +namespace llcoro +{ + +/// get the current coro::self& for those who really really care +LLCoros::coro::self& get_self(); + +/// Instantiate one of these in a block surrounding any leaf point when +/// control literally switches away from this coroutine. +class Suspending +{ +public: + Suspending(); + ~Suspending(); + +private: + LLCoros::coro::self* mSuspended; +}; + +} // namespace llcoro + #endif /* ! defined(LL_LLCOROS_H) */ diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp index be93e9c83b..b7e7edec5a 100755 --- a/indra/llcommon/lleventcoro.cpp +++ b/indra/llcommon/lleventcoro.cpp @@ -41,7 +41,23 @@ #include "llerror.h" #include "llcoros.h" -std::string LLEventDetail::listenerNameForCoro() +namespace +{ + +/** + * waitForEventOn() permits a coroutine to temporarily listen on an + * LLEventPump any number of times. We don't really want to have to ask + * the caller to label each such call with a distinct string; the whole + * point of waitForEventOn() is to present a nice sequential interface to + * the underlying LLEventPump-with-named-listeners machinery. So we'll use + * LLEventPump::inventName() to generate a distinct name for each + * temporary listener. On the other hand, because a given coroutine might + * call waitForEventOn() any number of times, we don't really want to + * consume an arbitrary number of generated inventName()s: that namespace, + * though large, is nonetheless finite. So we memoize an invented name for + * each distinct coroutine instance. + */ +std::string listenerNameForCoro() { // If this coroutine was launched by LLCoros::launch(), find that name. std::string name(LLCoros::instance().getName()); @@ -56,7 +72,25 @@ std::string LLEventDetail::listenerNameForCoro() return name; } -void LLEventDetail::storeToLLSDPath(LLSD& dest, const LLSD& rawPath, const LLSD& value) +/** + * Implement behavior described for postAndWait()'s @a replyPumpNamePath + * parameter: + * + * * If path.isUndefined(), do nothing. + * * If path.isString(), @a dest is an LLSD map: store @a value + * into dest[path.asString()]. + * * If path.isInteger(), @a dest is an LLSD array: store @a + * value into dest[path.asInteger()]. + * * If path.isArray(), iteratively apply the rules above to step + * down through the structure of @a dest. The last array entry in @a + * path specifies the entry in the lowest-level structure in @a dest + * into which to store @a value. + * + * @note + * In the degenerate case in which @a path is an empty array, @a dest will + * @em become @a value rather than @em containing it. + */ +void storeToLLSDPath(LLSD& dest, const LLSD& rawPath, const LLSD& value) { if (rawPath.isUndefined()) { @@ -109,14 +143,16 @@ void LLEventDetail::storeToLLSDPath(LLSD& dest, const LLSD& rawPath, const LLSD& *pdest = value; } -LLSD postAndWait(const LLSD& event, const LLEventPumpOrPumpName& requestPump, - const LLEventPumpOrPumpName& replyPump, const LLSD& replyPumpNamePath) +} // anonymous + +LLSD llcoro::postAndWait(const LLSD& event, const LLEventPumpOrPumpName& requestPump, + const LLEventPumpOrPumpName& replyPump, const LLSD& replyPumpNamePath) { // declare the future - boost::dcoroutines::future future(LLCoros::get_self()); + boost::dcoroutines::future future(llcoro::get_self()); // make a callback that will assign a value to the future, and listen on // the specified LLEventPump with that callback - std::string listenerName(LLEventDetail::listenerNameForCoro()); + std::string listenerName(listenerNameForCoro()); LLTempBoundListener connection( replyPump.getPump().listen(listenerName, voidlistener(boost::dcoroutines::make_callback(future)))); @@ -126,7 +162,7 @@ LLSD postAndWait(const LLSD& event, const LLEventPumpOrPumpName& requestPump, // If replyPumpNamePath is non-empty, store the replyPump name in the // request event. LLSD modevent(event); - LLEventDetail::storeToLLSDPath(modevent, replyPumpNamePath, replyPump.getPump().getName()); + storeToLLSDPath(modevent, replyPumpNamePath, replyPump.getPump().getName()); LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << listenerName << " posting to " << requestPump.getPump().getName() << LL_ENDL; @@ -142,7 +178,7 @@ LLSD postAndWait(const LLSD& event, const LLEventPumpOrPumpName& requestPump, LLSD value; { // instantiate Suspending to manage the "current" coroutine - LLCoros::Suspending suspended; + llcoro::Suspending suspended; value = *future; } // destroy Suspending as soon as we're back LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << listenerName @@ -151,6 +187,53 @@ LLSD postAndWait(const LLSD& event, const LLEventPumpOrPumpName& requestPump, return value; } +namespace +{ + +/** + * This helper is specifically for the two-pump version of waitForEventOn(). + * We use a single future object, but we want to listen on two pumps with it. + * Since we must still adapt from (the callable constructed by) + * boost::dcoroutines::make_callback() (void return) to provide an event + * listener (bool return), we've adapted VoidListener for the purpose. The + * basic idea is that we construct a distinct instance of WaitForEventOnHelper + * -- binding different instance data -- for each of the pumps. Then, when a + * pump delivers an LLSD value to either WaitForEventOnHelper, it can combine + * that LLSD with its discriminator to feed the future object. + */ +template +class WaitForEventOnHelper +{ +public: + WaitForEventOnHelper(const LISTENER& listener, int discriminator): + mListener(listener), + mDiscrim(discriminator) + {} + // this signature is required for an LLEventPump listener + bool operator()(const LLSD& event) + { + // our future object is defined to accept LLEventWithID + mListener(LLEventWithID(event, mDiscrim)); + // don't swallow the event, let other listeners see it + return false; + } +private: + LISTENER mListener; + const int mDiscrim; +}; + +/// WaitForEventOnHelper type-inference helper +template +WaitForEventOnHelper wfeoh(const LISTENER& listener, int discriminator) +{ + return WaitForEventOnHelper(listener, discriminator); +} + +} // anonymous + +namespace llcoro +{ + LLEventWithID postAndWait2(const LLSD& event, const LLEventPumpOrPumpName& requestPump, const LLEventPumpOrPumpName& replyPump0, @@ -159,26 +242,26 @@ LLEventWithID postAndWait2(const LLSD& event, const LLSD& replyPump1NamePath) { // declare the future - boost::dcoroutines::future future(LLCoros::get_self()); + boost::dcoroutines::future future(llcoro::get_self()); // either callback will assign a value to this future; listen on // each specified LLEventPump with a callback - std::string name(LLEventDetail::listenerNameForCoro()); + std::string name(listenerNameForCoro()); LLTempBoundListener connection0( replyPump0.getPump().listen(name + "a", - LLEventDetail::wfeoh(boost::dcoroutines::make_callback(future), 0))); + wfeoh(boost::dcoroutines::make_callback(future), 0))); LLTempBoundListener connection1( replyPump1.getPump().listen(name + "b", - LLEventDetail::wfeoh(boost::dcoroutines::make_callback(future), 1))); + wfeoh(boost::dcoroutines::make_callback(future), 1))); // skip the "post" part if requestPump is default-constructed if (requestPump) { // If either replyPumpNamePath is non-empty, store the corresponding // replyPump name in the request event. LLSD modevent(event); - LLEventDetail::storeToLLSDPath(modevent, replyPump0NamePath, - replyPump0.getPump().getName()); - LLEventDetail::storeToLLSDPath(modevent, replyPump1NamePath, - replyPump1.getPump().getName()); + storeToLLSDPath(modevent, replyPump0NamePath, + replyPump0.getPump().getName()); + storeToLLSDPath(modevent, replyPump1NamePath, + replyPump1.getPump().getName()); LL_DEBUGS("lleventcoro") << "postAndWait2(): coroutine " << name << " posting to " << requestPump.getPump().getName() << ": " << modevent << LL_ENDL; @@ -191,7 +274,7 @@ LLEventWithID postAndWait2(const LLSD& event, LLEventWithID value; { // instantiate Suspending to manage "current" coroutine - LLCoros::Suspending suspended; + llcoro::Suspending suspended; value = *future; } // destroy Suspending as soon as we're back LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << name @@ -227,3 +310,5 @@ LLSD errorLog(const LLEventWithID& result, const std::string& desc) // A simple return must therefore be from the reply pump (pump 0). return result.first; } + +} // namespace llcoro diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h index daf9360a2e..2a60f2b1e0 100755 --- a/indra/llcommon/lleventcoro.h +++ b/indra/llcommon/lleventcoro.h @@ -72,13 +72,16 @@ private: boost::optional mPump; }; +namespace llcoro +{ + /// This is an adapter for a signature like void LISTENER(const LLSD&), which /// isn't a valid LLEventPump listener: such listeners should return bool. template -class LLVoidListener +class VoidListener { public: - LLVoidListener(const LISTENER& listener): + VoidListener(const LISTENER& listener): mListener(listener) {} bool operator()(const LLSD& event) @@ -91,51 +94,13 @@ private: LISTENER mListener; }; -/// LLVoidListener helper function to infer the type of the LISTENER +/// VoidListener helper function to infer the type of the LISTENER template -LLVoidListener voidlistener(const LISTENER& listener) +VoidListener voidlistener(const LISTENER& listener) { - return LLVoidListener(listener); + return VoidListener(listener); } -namespace LLEventDetail -{ - /** - * waitForEventOn() permits a coroutine to temporarily listen on an - * LLEventPump any number of times. We don't really want to have to ask - * the caller to label each such call with a distinct string; the whole - * point of waitForEventOn() is to present a nice sequential interface to - * the underlying LLEventPump-with-named-listeners machinery. So we'll use - * LLEventPump::inventName() to generate a distinct name for each - * temporary listener. On the other hand, because a given coroutine might - * call waitForEventOn() any number of times, we don't really want to - * consume an arbitrary number of generated inventName()s: that namespace, - * though large, is nonetheless finite. So we memoize an invented name for - * each distinct coroutine instance. - */ - std::string listenerNameForCoro(); - - /** - * Implement behavior described for postAndWait()'s @a replyPumpNamePath - * parameter: - * - * * If path.isUndefined(), do nothing. - * * If path.isString(), @a dest is an LLSD map: store @a value - * into dest[path.asString()]. - * * If path.isInteger(), @a dest is an LLSD array: store @a - * value into dest[path.asInteger()]. - * * If path.isArray(), iteratively apply the rules above to step - * down through the structure of @a dest. The last array entry in @a - * path specifies the entry in the lowest-level structure in @a dest - * into which to store @a value. - * - * @note - * In the degenerate case in which @a path is an empty array, @a dest will - * @em become @a value rather than @em containing it. - */ - LL_COMMON_API void storeToLLSDPath(LLSD& dest, const LLSD& path, const LLSD& value); -} // namespace LLEventDetail - /** * Post specified LLSD event on the specified LLEventPump, then wait for a * response on specified other LLEventPump. This is more than mere @@ -196,50 +161,13 @@ LLSD waitForEventOn(const LLEventPumpOrPumpName& pump) return postAndWait(LLSD(), LLEventPumpOrPumpName(), pump); } +} // namespace llcoro + /// return type for two-pump variant of waitForEventOn() typedef std::pair LLEventWithID; -namespace LLEventDetail +namespace llcoro { - /** - * This helper is specifically for the two-pump version of waitForEventOn(). - * We use a single future object, but we want to listen on two pumps with it. - * Since we must still adapt from (the callable constructed by) - * boost::dcoroutines::make_callback() (void return) to provide an event - * listener (bool return), we've adapted LLVoidListener for the purpose. The - * basic idea is that we construct a distinct instance of WaitForEventOnHelper - * -- binding different instance data -- for each of the pumps. Then, when a - * pump delivers an LLSD value to either WaitForEventOnHelper, it can combine - * that LLSD with its discriminator to feed the future object. - */ - template - class WaitForEventOnHelper - { - public: - WaitForEventOnHelper(const LISTENER& listener, int discriminator): - mListener(listener), - mDiscrim(discriminator) - {} - // this signature is required for an LLEventPump listener - bool operator()(const LLSD& event) - { - // our future object is defined to accept LLEventWithID - mListener(LLEventWithID(event, mDiscrim)); - // don't swallow the event, let other listeners see it - return false; - } - private: - LISTENER mListener; - const int mDiscrim; - }; - - /// WaitForEventOnHelper type-inference helper - template - WaitForEventOnHelper wfeoh(const LISTENER& listener, int discriminator) - { - return WaitForEventOnHelper(listener, discriminator); - } -} // namespace LLEventDetail /** * This function waits for a reply on either of two specified LLEventPumps. @@ -334,6 +262,8 @@ private: */ LL_COMMON_API LLSD errorLog(const LLEventWithID& result, const std::string& desc); +} // namespace llcoro + /** * Certain event APIs require the name of an LLEventPump on which they should * post results. While it works to invent a distinct name and let @@ -365,13 +295,13 @@ public: */ LLSD wait() { - return ::waitForEventOn(mPump); + return llcoro::waitForEventOn(mPump); } LLSD postAndWait(const LLSD& event, const LLEventPumpOrPumpName& requestPump, const LLSD& replyPumpNamePath=LLSD()) { - return ::postAndWait(event, requestPump, mPump, replyPumpNamePath); + return llcoro::postAndWait(event, requestPump, mPump, replyPumpNamePath); } private: @@ -410,19 +340,19 @@ public: /// waitForEventOn(either of our two LLEventPumps) LLEventWithID wait() { - return waitForEventOn(mPump0, mPump1); + return llcoro::waitForEventOn(mPump0, mPump1); } /// errorException(wait()) LLSD waitWithException() { - return errorException(wait(), std::string("Error event on ") + getName1()); + return llcoro::errorException(wait(), std::string("Error event on ") + getName1()); } /// errorLog(wait()) LLSD waitWithLog() { - return errorLog(wait(), std::string("Error event on ") + getName1()); + return llcoro::errorLog(wait(), std::string("Error event on ") + getName1()); } LLEventWithID postAndWait(const LLSD& event, @@ -430,8 +360,8 @@ public: const LLSD& replyPump0NamePath=LLSD(), const LLSD& replyPump1NamePath=LLSD()) { - return postAndWait2(event, requestPump, mPump0, mPump1, - replyPump0NamePath, replyPump1NamePath); + return llcoro::postAndWait2(event, requestPump, mPump0, mPump1, + replyPump0NamePath, replyPump1NamePath); } LLSD postAndWaitWithException(const LLSD& event, @@ -439,9 +369,9 @@ public: const LLSD& replyPump0NamePath=LLSD(), const LLSD& replyPump1NamePath=LLSD()) { - return errorException(postAndWait(event, requestPump, - replyPump0NamePath, replyPump1NamePath), - std::string("Error event on ") + getName1()); + return llcoro::errorException(postAndWait(event, requestPump, + replyPump0NamePath, replyPump1NamePath), + std::string("Error event on ") + getName1()); } LLSD postAndWaitWithLog(const LLSD& event, @@ -449,9 +379,9 @@ public: const LLSD& replyPump0NamePath=LLSD(), const LLSD& replyPump1NamePath=LLSD()) { - return errorLog(postAndWait(event, requestPump, - replyPump0NamePath, replyPump1NamePath), - std::string("Error event on ") + getName1()); + return llcoro::errorLog(postAndWait(event, requestPump, + replyPump0NamePath, replyPump1NamePath), + std::string("Error event on ") + getName1()); } private: diff --git a/indra/llcommon/tests/lleventcoro_test.cpp b/indra/llcommon/tests/lleventcoro_test.cpp index da927038ab..79bcfe58ed 100755 --- a/indra/llcommon/tests/lleventcoro_test.cpp +++ b/indra/llcommon/tests/lleventcoro_test.cpp @@ -86,6 +86,8 @@ #include "lleventcoro.h" #include "../test/debug.h" +using namespace llcoro; + /***************************************************************************** * from the banana.cpp example program borrowed for test<1>() *****************************************************************************/ @@ -259,8 +261,7 @@ namespace tut // Construct the coroutine instance that will run explicit_wait. // Pass the ctor a callable that accepts the coroutine_type::self // param passed by the library. - boost::dcoroutines::coroutine - coro(explicit_wait); + boost::dcoroutines::coroutine coro(explicit_wait); // Start the coroutine coro(std::nothrow); // When the coroutine waits for the event pump, it returns here. diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index ac1c2f8e58..cd3c527241 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -596,7 +596,7 @@ LLSD HttpCoroutineAdapter::postAndYield_(LLCore::HttpRequest::ptr_t &request, } saveState(hhandle, request, handler); - LLSD results = waitForEventOn(handler->getReplyPump()); + LLSD results = llcoro::waitForEventOn(handler->getReplyPump()); cleanState(); return results; @@ -697,7 +697,7 @@ LLSD HttpCoroutineAdapter::postAndYield_(LLCore::HttpRequest::ptr_t &request, } saveState(hhandle, request, handler); - LLSD results = waitForEventOn(handler->getReplyPump()); + LLSD results = llcoro::waitForEventOn(handler->getReplyPump()); cleanState(); //LL_INFOS() << "Results for transaction " << transactionId << LL_ENDL; @@ -735,7 +735,7 @@ LLSD HttpCoroutineAdapter::putAndYield_(LLCore::HttpRequest::ptr_t &request, } saveState(hhandle, request, handler); - LLSD results = waitForEventOn(handler->getReplyPump()); + LLSD results = llcoro::waitForEventOn(handler->getReplyPump()); cleanState(); //LL_INFOS() << "Results for transaction " << transactionId << LL_ENDL; return results; @@ -790,7 +790,7 @@ LLSD HttpCoroutineAdapter::getAndYield_(LLCore::HttpRequest::ptr_t &request, } saveState(hhandle, request, handler); - LLSD results = waitForEventOn(handler->getReplyPump()); + LLSD results = llcoro::waitForEventOn(handler->getReplyPump()); cleanState(); //LL_INFOS() << "Results for transaction " << transactionId << LL_ENDL; return results; @@ -825,7 +825,7 @@ LLSD HttpCoroutineAdapter::deleteAndYield_(LLCore::HttpRequest::ptr_t &request, } saveState(hhandle, request, handler); - LLSD results = waitForEventOn(handler->getReplyPump()); + LLSD results = llcoro::waitForEventOn(handler->getReplyPump()); cleanState(); //LL_INFOS() << "Results for transaction " << transactionId << LL_ENDL; return results; diff --git a/indra/newview/llcoproceduremanager.cpp b/indra/newview/llcoproceduremanager.cpp index 1a4a906f35..d3168985f8 100644 --- a/indra/newview/llcoproceduremanager.cpp +++ b/indra/newview/llcoproceduremanager.cpp @@ -138,7 +138,7 @@ void LLCoprocedureManager::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineA while (!mShutdown) { - waitForEventOn(mWakeupTrigger); + llcoro::waitForEventOn(mWakeupTrigger); if (mShutdown) break; diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 54da226209..0aad1d5ba9 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -197,7 +197,7 @@ namespace Details " seconds, error count is now " << errorCount << LL_ENDL; timeout.eventAfter(waitToRetry, LLSD()); - waitForEventOn(timeout); + llcoro::waitForEventOn(timeout); if (mDone) break; diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp index 0569e9f3e8..88415ff11a 100755 --- a/indra/viewer_components/login/lllogin.cpp +++ b/indra/viewer_components/login/lllogin.cpp @@ -175,7 +175,7 @@ void LLLogin::Impl::login_(std::string uri, LLSD login_params) request["op"] = "rewriteURI"; request["uri"] = uri; request["reply"] = replyPump.getName(); - rewrittenURIs = postAndWait(request, srv_pump_name, filter); + rewrittenURIs = llcoro::postAndWait(request, srv_pump_name, filter); // EXP-772: If rewrittenURIs fail, try original URI as a fallback. rewrittenURIs.append(uri); } // we no longer need the filter @@ -221,10 +221,10 @@ void LLLogin::Impl::login_(std::string uri, LLSD login_params) // returns. Subsequent responses, of course, must be awaited // without posting again. for (mAuthResponse = validateResponse(loginReplyPump.getName(), - postAndWait(request, xmlrpcPump, loginReplyPump, "reply")); + llcoro::postAndWait(request, xmlrpcPump, loginReplyPump, "reply")); mAuthResponse["status"].asString() == "Downloading"; mAuthResponse = validateResponse(loginReplyPump.getName(), - waitForEventOn(loginReplyPump))) + llcoro::waitForEventOn(loginReplyPump))) { // Still Downloading -- send progress update. sendProgressEvent("offline", "downloading"); -- cgit v1.2.3 From d34476359e59a1902b1498fbed94daca3d20bff1 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 3 Jul 2015 09:57:02 -0400 Subject: MAINT-5357: Extract LLErrorEvent to global namespace. This exception class got inadvertently swept up into the llcoro namespace. Its LLClassConvention name is intended for use in the global namespace. As there are no current references, this is a trivial change. --- indra/llcommon/lleventcoro.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h index 2a60f2b1e0..f1c5dc2fde 100755 --- a/indra/llcommon/lleventcoro.h +++ b/indra/llcommon/lleventcoro.h @@ -236,6 +236,8 @@ waitForEventOn(const LLEventPumpOrPumpName& pump0, const LLEventPumpOrPumpName& */ LLSD errorException(const LLEventWithID& result, const std::string& desc); +} // namespace llcoro + /** * Exception thrown by errorException(). We don't call this LLEventError * because it's not an error in event processing: rather, this exception @@ -256,6 +258,9 @@ private: LLSD mData; }; +namespace llcoro +{ + /** * Like errorException(), save that this trips a fatal error using LL_ERRS * rather than throwing an exception. -- cgit v1.2.3 From 1d2514956f15f780aaead9bc123c1353a5b7fd20 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 4 Jul 2015 19:58:03 -0400 Subject: MAINT-5357: Add llcoro::yield() function to yield for one frame. --- indra/llcommon/lleventcoro.cpp | 8 ++++++++ indra/llcommon/lleventcoro.h | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp index b7e7edec5a..ad02e139b8 100755 --- a/indra/llcommon/lleventcoro.cpp +++ b/indra/llcommon/lleventcoro.cpp @@ -145,6 +145,14 @@ void storeToLLSDPath(LLSD& dest, const LLSD& rawPath, const LLSD& value) } // anonymous +void llcoro::yield() +{ + // By viewer convention, we post an event on the "mainloop" LLEventPump + // each iteration of the main event-handling loop. So waiting for a single + // event on "mainloop" gives us a one-frame yield. + waitForEventOn("mainloop"); +} + LLSD llcoro::postAndWait(const LLSD& event, const LLEventPumpOrPumpName& requestPump, const LLEventPumpOrPumpName& replyPump, const LLSD& replyPumpNamePath) { diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h index f1c5dc2fde..e2ce4bb193 100755 --- a/indra/llcommon/lleventcoro.h +++ b/indra/llcommon/lleventcoro.h @@ -101,6 +101,13 @@ VoidListener voidlistener(const LISTENER& listener) return VoidListener(listener); } +/** + * Yield control from a coroutine for one "mainloop" tick. If your coroutine + * runs without suspending for nontrivial time, sprinkle in calls to this + * function to avoid stalling the rest of the viewer processing. + */ +void yield(); + /** * Post specified LLSD event on the specified LLEventPump, then wait for a * response on specified other LLEventPump. This is more than mere -- cgit v1.2.3