diff options
Diffstat (limited to 'indra/llcommon/lleventcoro.cpp')
-rwxr-xr-x | indra/llcommon/lleventcoro.cpp | 135 |
1 files changed, 74 insertions, 61 deletions
diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp index 9b7e8fb65f..578a2b62c8 100755 --- a/indra/llcommon/lleventcoro.cpp +++ b/indra/llcommon/lleventcoro.cpp @@ -34,12 +34,11 @@ #include <map> // std headers // external library headers -#include <boost/dcoroutine/coroutine.hpp> -#include <boost/dcoroutine/future.hpp> // other Linden headers #include "llsdserialize.h" #include "llerror.h" #include "llcoros.h" +#include "llmake.h" #include "lleventfilter.h" @@ -145,6 +144,36 @@ void storeToLLSDPath(LLSD& dest, const LLSD& rawPath, const LLSD& value) *pdest = value; } +/// For LLCoros::Future<LLSD>::make_callback(), the callback has a signature +/// like void callback(LLSD), which isn't a valid LLEventPump listener: such +/// listeners must return bool. +template <typename LISTENER> +class FutureListener +{ +public: + // FutureListener is instantiated on the coroutine stack: the stack, in + // other words, that wants to suspend. + FutureListener(const LISTENER& listener): + mListener(listener), + // Capture the suspending coroutine's flag as a consuming or + // non-consuming listener. + mConsume(LLCoros::get_consuming()) + {} + + // operator()() is called on the main stack: the stack on which the + // expected event is fired. + bool operator()(const LLSD& event) + { + mListener(event); + // tell upstream LLEventPump whether listener consumed + return mConsume; + } + +protected: + LISTENER mListener; + bool mConsume; +}; + } // anonymous void llcoro::suspend() @@ -167,13 +196,13 @@ LLSD llcoro::postAndSuspend(const LLSD& event, const LLEventPumpOrPumpName& requ const LLEventPumpOrPumpName& replyPump, const LLSD& replyPumpNamePath) { // declare the future - boost::dcoroutines::future<LLSD_consumed> future(LLCoros::get_self()); + LLCoros::Future<LLSD> future; // make a callback that will assign a value to the future, and listen on // the specified LLEventPump with that callback std::string listenerName(listenerNameForCoro()); LLTempBoundListener connection( replyPump.getPump().listen(listenerName, - voidlistener(boost::dcoroutines::make_callback(future)))); + llmake<FutureListener>(future.make_callback()))); // skip the "post" part if requestPump is default-constructed if (requestPump) { @@ -192,67 +221,56 @@ LLSD llcoro::postAndSuspend(const LLSD& event, const LLEventPumpOrPumpName& requ LL_DEBUGS("lleventcoro") << "postAndSuspend(): coroutine " << listenerName << " about to wait on LLEventPump " << replyPump.getPump().getName() << LL_ENDL; - // trying to dereference ("resolve") the future makes us wait for it - LLSD_consumed value; - { - // instantiate Suspending to manage the "current" coroutine - llcoro::Suspending suspended; - value = *future; - } // destroy Suspending as soon as we're back + // calling get() on the future makes us wait for it + LLSD value(future.get()); LL_DEBUGS("lleventcoro") << "postAndSuspend(): coroutine " << listenerName - << " resuming with " << value.first << LL_ENDL; - // immediately set consumed according to consuming - *value.second = LLCoros::get_consuming(); + << " resuming with " << value << LL_ENDL; // returning should disconnect the connection - return value.first; + return value; } namespace { -typedef std::pair<LLEventWithID, bool*> LLEventWithID_consumed; - /** - * This helper is specifically for the two-pump version of suspendUntilEventOn(). - * 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. + * This helper is specifically for postAndSuspend2(). 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 + * FutureListener for the purpose. The basic idea is that we construct a + * distinct instance of FutureListener2 -- binding different instance data -- + * for each of the pumps. Then, when a pump delivers an LLSD value to either + * FutureListener2, it can combine that LLSD with its discriminator to feed + * the future object. + * + * DISCRIM is a template argument so we can use llmake() rather than + * having to write our own argument-deducing helper function. */ -template <typename LISTENER> -class WaitForEventOnHelper +template <typename LISTENER, typename DISCRIM> +class FutureListener2: public FutureListener<LISTENER> { + typedef FutureListener<LISTENER> super; + public: - WaitForEventOnHelper(const LISTENER& listener, int discriminator): - mListener(listener), + // instantiated on coroutine stack: the stack about to suspend + FutureListener2(const LISTENER& listener, DISCRIM discriminator): + super(listener), mDiscrim(discriminator) {} - // this signature is required for an LLEventPump listener + // called on main stack: the stack on which event is fired bool operator()(const LLSD& event) { - bool consumed = false; - // our future object is defined to accept LLEventWithID_consumed - mListener(LLEventWithID_consumed(LLEventWithID(event, mDiscrim), &consumed)); + // our future object is defined to accept LLEventWithID + super::mListener(LLEventWithID(event, mDiscrim)); // tell LLEventPump whether or not event was consumed - return consumed; + return super::mConsume; } + private: - LISTENER mListener; - const int mDiscrim; + const DISCRIM mDiscrim; }; -/// WaitForEventOnHelper type-inference helper -template <typename LISTENER> -WaitForEventOnHelper<LISTENER> wfeoh(const LISTENER& listener, int discriminator) -{ - return WaitForEventOnHelper<LISTENER>(listener, discriminator); -} - } // anonymous namespace llcoro @@ -266,16 +284,18 @@ LLEventWithID postAndSuspend2(const LLSD& event, const LLSD& replyPump1NamePath) { // declare the future - boost::dcoroutines::future<LLEventWithID_consumed> future(LLCoros::get_self()); + LLCoros::Future<LLEventWithID> future; // 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))); + replyPump0.getPump().listen( + name + "a", + llmake<FutureListener2>(future.make_callback(), 0))); LLTempBoundListener connection1( - replyPump1.getPump().listen(name + "b", - wfeoh(boost::dcoroutines::make_callback(future), 1))); + replyPump1.getPump().listen( + name + "b", + llmake<FutureListener2>(future.make_callback(), 1))); // skip the "post" part if requestPump is default-constructed if (requestPump) { @@ -294,20 +314,13 @@ LLEventWithID postAndSuspend2(const LLSD& event, LL_DEBUGS("lleventcoro") << "postAndSuspend2(): 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_consumed value; - { - // instantiate Suspending to manage "current" coroutine - llcoro::Suspending suspended; - value = *future; - } // destroy Suspending as soon as we're back + // calling get() on the future makes us wait for it + LLEventWithID value(future.get()); LL_DEBUGS("lleventcoro") << "postAndSuspend(): coroutine " << name - << " resuming with (" << value.first.first - << ", " << value.first.second << ")" << LL_ENDL; - // tell LLEventPump whether we're consuming - *value.second = LLCoros::get_consuming(); + << " resuming with (" << value.first << ", " << value.second << ")" + << LL_ENDL; // returning should disconnect both connections - return value.first; + return value; } LLSD errorException(const LLEventWithID& result, const std::string& desc) |