diff options
Diffstat (limited to 'indra/llcommon')
-rwxr-xr-x | indra/llcommon/llcoros.cpp | 4 | ||||
-rwxr-xr-x | indra/llcommon/llcoros.h | 12 | ||||
-rwxr-xr-x | indra/llcommon/lleventcoro.cpp | 129 | ||||
-rwxr-xr-x | indra/llcommon/lleventcoro.h | 18 | ||||
-rwxr-xr-x | indra/llcommon/tests/lleventcoro_test.cpp | 3 |
5 files changed, 98 insertions, 68 deletions
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index d76401d01b..6cca5e7c60 100755 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -61,7 +61,7 @@ LLCoros::coro::self& LLCoros::get_self() return *current->mSelf; } -llcoro::Suspending::Suspending(): +LLCoros::Suspending::Suspending(): mSuspended(LLCoros::sCurrentCoro.get()) { // Revert mCurrentCoro to the value it had at the moment we last switched @@ -69,7 +69,7 @@ llcoro::Suspending::Suspending(): LLCoros::sCurrentCoro.reset(mSuspended->mPrev); } -llcoro::Suspending::~Suspending() +LLCoros::Suspending::~Suspending() { // Okay, we're back, update our mPrev mSuspended->mPrev = LLCoros::sCurrentCoro.get(); diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 56eed8cafe..05bd87dc3c 100755 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -144,6 +144,18 @@ 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); diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp index 85af0d9b9f..a37b87f085 100755 --- a/indra/llcommon/lleventcoro.cpp +++ b/indra/llcommon/lleventcoro.cpp @@ -41,7 +41,7 @@ #include "llerror.h" #include "llcoros.h" -namespace +std::string LLEventDetail::listenerNameForCoro() { /** @@ -143,24 +143,14 @@ void storeToLLSDPath(LLSD& dest, const LLSD& rawPath, const LLSD& value) *pdest = 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) +LLSD postAndWait(const LLSD& event, const LLEventPumpOrPumpName& requestPump, + const LLEventPumpOrPumpName& replyPump, const LLSD& replyPumpNamePath) { // declare the future boost::dcoroutines::future<LLSD> future(LLCoros::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(listenerNameForCoro()); + std::string listenerName(LLEventDetail::listenerNameForCoro()); LLTempBoundListener connection( replyPump.getPump().listen(listenerName, voidlistener(boost::dcoroutines::make_callback(future)))); @@ -170,7 +160,7 @@ LLSD llcoro::postAndWait(const LLSD& event, const LLEventPumpOrPumpName& request // If replyPumpNamePath is non-empty, store the replyPump name in the // request event. LLSD modevent(event); - storeToLLSDPath(modevent, replyPumpNamePath, replyPump.getPump().getName()); + LLEventDetail::storeToLLSDPath(modevent, replyPumpNamePath, replyPump.getPump().getName()); LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << listenerName << " posting to " << requestPump.getPump().getName() << LL_ENDL; @@ -186,7 +176,7 @@ LLSD llcoro::postAndWait(const LLSD& event, const LLEventPumpOrPumpName& request LLSD value; { // instantiate Suspending to manage the "current" coroutine - llcoro::Suspending suspended; + LLCoros::Suspending suspended; value = *future; } // destroy Suspending as soon as we're back LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << listenerName @@ -195,6 +185,72 @@ LLSD llcoro::postAndWait(const LLSD& event, const LLEventPumpOrPumpName& request return value; } +LLEventWithID postAndWait2(const LLSD& event, + const LLEventPumpOrPumpName& requestPump, + const LLEventPumpOrPumpName& replyPump0, + const LLEventPumpOrPumpName& replyPump1, + const LLSD& replyPump0NamePath, + const LLSD& replyPump1NamePath) +{ + // declare the future + boost::dcoroutines::future<LLEventWithID> future(LLCoros::get_self()); + // either callback will assign a value to this future; listen on + // each specified LLEventPump with a callback + std::string name(LLEventDetail::listenerNameForCoro()); + LLTempBoundListener connection0( + replyPump0.getPump().listen(name + "a", + LLEventDetail::wfeoh(boost::dcoroutines::make_callback(future), 0))); + LLTempBoundListener connection1( + replyPump1.getPump().listen(name + "b", + LLEventDetail::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()); + LL_DEBUGS("lleventcoro") << "postAndWait2(): coroutine " << name + << " posting to " << requestPump.getPump().getName() + << ": " << modevent << LL_ENDL; + requestPump.getPump().post(modevent); + } + LL_DEBUGS("lleventcoro") << "postAndWait2(): coroutine " << name + << " about to wait on LLEventPumps " << replyPump0.getPump().getName() + << ", " << replyPump1.getPump().getName() << LL_ENDL; + // trying to dereference ("resolve") the future makes us wait for it + LLEventWithID value; + { + // instantiate Suspending to manage "current" coroutine + LLCoros::Suspending suspended; + value = *future; + } // destroy Suspending as soon as we're back + LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << name + << " resuming with (" << value.first << ", " << value.second << ")" + << LL_ENDL; + // returning should disconnect both connections + return 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) + boost::dcoroutines::future<LLSD> future(llcoro::get_self()); + std::string listenerName(listenerNameForCoro()); + storeToLLSDPath(modevent, replyPumpNamePath, replyPump.getPump().getName()); + llcoro::Suspending suspended; namespace { @@ -242,56 +298,15 @@ WaitForEventOnHelper<LISTENER> wfeoh(const LISTENER& listener, int discriminator namespace llcoro { -LLEventWithID postAndWait2(const LLSD& event, - const LLEventPumpOrPumpName& requestPump, - const LLEventPumpOrPumpName& replyPump0, - const LLEventPumpOrPumpName& replyPump1, - const LLSD& replyPump0NamePath, - const LLSD& replyPump1NamePath) -{ - // declare the future boost::dcoroutines::future<LLEventWithID> future(LLCoros::get_self()); - // either callback will assign a value to this future; listen on - // each specified LLEventPump with a callback std::string name(listenerNameForCoro()); - LLTempBoundListener connection0( - replyPump0.getPump().listen(name + "a", wfeoh(boost::dcoroutines::make_callback(future), 0))); - LLTempBoundListener connection1( - replyPump1.getPump().listen(name + "b", 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); 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; - requestPump.getPump().post(modevent); - } - LL_DEBUGS("lleventcoro") << "postAndWait2(): coroutine " << name - << " about to wait on LLEventPumps " << replyPump0.getPump().getName() - << ", " << replyPump1.getPump().getName() << LL_ENDL; - // trying to dereference ("resolve") the future makes us wait for it - LLEventWithID value; - { - // instantiate Suspending to manage "current" coroutine llcoro::Suspending suspended; - value = *future; - } // destroy Suspending as soon as we're back - LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << name - << " resuming with (" << value.first << ", " << value.second << ")" - << LL_ENDL; - // returning should disconnect both connections - return value; -} - LLSD errorException(const LLEventWithID& result, const std::string& desc) { // If the result arrived on the error pump (pump 1), instead of diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h index e2ce4bb193..20fc422a68 100755 --- a/indra/llcommon/lleventcoro.h +++ b/indra/llcommon/lleventcoro.h @@ -101,6 +101,8 @@ VoidListener<LISTENER> voidlistener(const LISTENER& listener) return VoidListener<LISTENER>(listener); } + * each distinct coroutine instance. + std::string listenerNameForCoro(); /** * Yield control from a coroutine for one "mainloop" tick. If your coroutine * runs without suspending for nontrivial time, sprinkle in calls to this @@ -307,13 +309,13 @@ public: */ LLSD wait() { - return llcoro::waitForEventOn(mPump); + return ::waitForEventOn(mPump); } LLSD postAndWait(const LLSD& event, const LLEventPumpOrPumpName& requestPump, const LLSD& replyPumpNamePath=LLSD()) { - return llcoro::postAndWait(event, requestPump, mPump, replyPumpNamePath); + return ::postAndWait(event, requestPump, mPump, replyPumpNamePath); } private: @@ -352,19 +354,19 @@ public: /// waitForEventOn(either of our two LLEventPumps) LLEventWithID wait() { - return llcoro::waitForEventOn(mPump0, mPump1); + return waitForEventOn(mPump0, mPump1); } /// errorException(wait()) LLSD waitWithException() { - return llcoro::errorException(wait(), std::string("Error event on ") + getName1()); + return errorException(wait(), std::string("Error event on ") + getName1()); } /// errorLog(wait()) LLSD waitWithLog() { - return llcoro::errorLog(wait(), std::string("Error event on ") + getName1()); + return errorLog(wait(), std::string("Error event on ") + getName1()); } LLEventWithID postAndWait(const LLSD& event, @@ -372,7 +374,7 @@ public: const LLSD& replyPump0NamePath=LLSD(), const LLSD& replyPump1NamePath=LLSD()) { - return llcoro::postAndWait2(event, requestPump, mPump0, mPump1, + return postAndWait2(event, requestPump, mPump0, mPump1, replyPump0NamePath, replyPump1NamePath); } @@ -381,7 +383,7 @@ public: const LLSD& replyPump0NamePath=LLSD(), const LLSD& replyPump1NamePath=LLSD()) { - return llcoro::errorException(postAndWait(event, requestPump, + return errorException(postAndWait(event, requestPump, replyPump0NamePath, replyPump1NamePath), std::string("Error event on ") + getName1()); } @@ -391,7 +393,7 @@ public: const LLSD& replyPump0NamePath=LLSD(), const LLSD& replyPump1NamePath=LLSD()) { - return llcoro::errorLog(postAndWait(event, requestPump, + return errorLog(postAndWait(event, requestPump, replyPump0NamePath, replyPump1NamePath), std::string("Error event on ") + getName1()); } diff --git a/indra/llcommon/tests/lleventcoro_test.cpp b/indra/llcommon/tests/lleventcoro_test.cpp index 00be5035f2..b8d9d8002f 100755 --- a/indra/llcommon/tests/lleventcoro_test.cpp +++ b/indra/llcommon/tests/lleventcoro_test.cpp @@ -264,7 +264,8 @@ 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<void()> coro(explicit_wait); + boost::dcoroutines::coroutine<void()> + coro(explicit_wait); // Start the coroutine coro(std::nothrow); // When the coroutine waits for the event pump, it returns here. |