From dd2311b993d137c538ca57b4360669db6d7fbfa0 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Tue, 26 Apr 2016 11:56:25 -0700 Subject: MAINT-6336: Put the timeout upstream of the suspending pump and fire the timeout it. Also some cleanup on LLSD construction in vivox. --- indra/llcommon/lleventcoro.cpp | 21 +++++++++--- indra/llcommon/lleventcoro.h | 5 ++- indra/llcommon/lleventfilter.h | 14 +++++++- indra/llcommon/llevents.h | 6 ++++ indra/newview/llvoicevivox.cpp | 77 ++++++++++++++---------------------------- 5 files changed, 65 insertions(+), 58 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp index 44291eb711..c8c43dc334 100755 --- a/indra/llcommon/lleventcoro.cpp +++ b/indra/llcommon/lleventcoro.cpp @@ -229,13 +229,26 @@ LLSD llcoro::postAndSuspend(const LLSD& event, const LLEventPumpOrPumpName& requ return value; } -LLSD llcoro::suspendUntilEventOnWithTimeout(const LLEventPumpOrPumpName& pump, F32 timeoutin, const LLSD &timeoutResult) +LLSD llcoro::suspendUntilEventOnWithTimeout(const LLEventPumpOrPumpName& suspendPumpOrName, + F32 timeoutin, const LLSD &timeoutResult) { - LLEventTimeout timeoutPump(pump); + /** + * The timeout pump is attached upstream of of the waiting pump and will + * pass the timeout event through it. We CAN NOT attach downstream since + * doing so will cause the suspendPump to fire any waiting events immediately + * and they will be lost. This becomes especially problematic with the + * LLEventTimeout(pump) constructor which will also attempt to fire those + * events using the virtual listen_impl method in the not yet fully constructed + * timeoutPump. + */ + LLEventTimeout timeoutPump; + LLEventPump &suspendPump = suspendPumpOrName.getPump(); + + LLTempBoundListener timeoutListener = timeoutPump.listen(suspendPump.getName(), + boost::bind(&LLEventPump::post, &suspendPump, _1)); timeoutPump.eventAfter(timeoutin, timeoutResult); - return llcoro::suspendUntilEventOn(timeoutPump); - + return llcoro::suspendUntilEventOn(suspendPump); } namespace diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h index 19c68e1f35..87926c692d 100755 --- a/indra/llcommon/lleventcoro.h +++ b/indra/llcommon/lleventcoro.h @@ -147,7 +147,10 @@ LLSD suspendUntilEventOn(const LLEventPumpOrPumpName& pump) return postAndSuspend(LLSD(), LLEventPumpOrPumpName(), pump); } -LLSD suspendUntilEventOnWithTimeout(const LLEventPumpOrPumpName& pump, F32 timeoutin, const LLSD &timeoutResult); +/// Suspend the coroutine until an event is fired on the identified pump +/// or the timeout duration has elapsed. If the timeout duration +/// elapses the specified LLSD is returned. +LLSD suspendUntilEventOnWithTimeout(const LLEventPumpOrPumpName& suspendPumpOrName, F32 timeoutin, const LLSD &timeoutResult); } // namespace llcoro diff --git a/indra/llcommon/lleventfilter.h b/indra/llcommon/lleventfilter.h index 15bac5fd73..66f3c14869 100755 --- a/indra/llcommon/lleventfilter.h +++ b/indra/llcommon/lleventfilter.h @@ -188,7 +188,19 @@ private: Action mAction; }; -/// Production implementation of LLEventTimoutBase +/** + * Production implementation of LLEventTimoutBase. + * + * @NOTE: Caution should be taken when using the LLEventTimeout(LLEventPump &) + * constructor to ensure that the upstream event pump is not an LLEventMaildrop + * or any other kind of store and forward pump which may have events outstanding. + * Using this constructor will cause the upstream event pump to fire any pending + * events and could result in the invocation of a virtual method before the timeout + * has been fully constructed. The timeout should instead be connected upstream + * from the event pump and attached using the listen method. + * See llcoro::suspendUntilEventOnWithTimeout() for an example. + */ + class LL_COMMON_API LLEventTimeout: public LLEventTimeoutBase { public: diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index 6175329a9d..ba4fcd766e 100755 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -616,6 +616,12 @@ public: * a queue. Subsequent attaching listeners will receive stored events from the queue * until a listener indicates that the event has been handled. In order to receive * multiple events from a mail drop the listener must disconnect and reconnect. + * + * @NOTE: When using an LLEventMailDrop (or LLEventQueue) with a LLEventTimeout or + * LLEventFilter attaching the filter downstream using Timeout's constructor will + * cause the MailDrop to discharge any of it's stored events. The timeout should + * instead be connected upstream using its listen() method. + * See llcoro::suspendUntilEventOnWithTimeout() for an example. */ class LL_COMMON_API LLEventMailDrop : public LLEventStream { diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 043ddc904b..2654666993 100755 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -900,8 +900,7 @@ bool LLVivoxVoiceClient::loginToVivox() { LLEventPump &voicePump = LLEventPumps::instance().obtain("vivoxClientPump"); - LLSD timeoutResult; - timeoutResult["login"] = LLSD::String("timeout"); + LLSD timeoutResult(LLSDMap("login", "timeout")); int loginRetryCount(0); @@ -1012,8 +1011,7 @@ void LLVivoxVoiceClient::logoutOfVivox(bool wait) if (wait) { LLEventPump &voicePump = LLEventPumps::instance().obtain("vivoxClientPump"); - LLSD timeoutResult; - timeoutResult["logout"] = LLSD::String("timeout"); + LLSD timeoutResult(LLSDMap("lougout", "timeout")); LLSD result = llcoro::suspendUntilEventOnWithTimeout(voicePump, LOGIN_ATTEMPT_TIMEOUT, timeoutResult); @@ -1216,8 +1214,7 @@ bool LLVivoxVoiceClient::addAndJoinSession(const sessionStatePtr_t &nextSession) bool added(true); bool joined(false); - LLSD timeoutResult; - timeoutResult["session"] = LLSD::String("timeout"); + LLSD timeoutResult(LLSDMap("session", "timeout")); // It appears that I need to wait for BOTH the SessionGroup.AddSession response and the SessionStateChangeEvent with state 4 // before continuing from this state. They can happen in either order, and if I don't wait for both, things can get stuck. @@ -1500,8 +1497,7 @@ bool LLVivoxVoiceClient::runSession(const sessionStatePtr_t &session) notifyParticipantObservers(); notifyVoiceFontObservers(); - LLSD timeoutEvent = LLSD::emptyMap(); - timeoutEvent["timeout"] = LLSD::Boolean(true); + LLSD timeoutEvent(LLSDMap("timeout", LLSD::Boolean(true))); LLEventPump &voicePump = LLEventPumps::instance().obtain("vivoxClientPump"); mIsInChannel = true; @@ -1653,8 +1649,7 @@ void LLVivoxVoiceClient::recordingAndPlaybackMode() int LLVivoxVoiceClient::voiceRecordBuffer() { - LLSD timeoutResult; - timeoutResult["recplay"] = LLSD::String("stop"); + LLSD timeoutResult(LLSDMap("recplay", "stop")); LL_INFOS("Voice") << "Recording voice buffer" << LL_ENDL; @@ -1684,8 +1679,7 @@ int LLVivoxVoiceClient::voiceRecordBuffer() int LLVivoxVoiceClient::voicePlaybackBuffer() { - LLSD timeoutResult; - timeoutResult["recplay"] = LLSD::String("stop"); + LLSD timeoutResult(LLSDMap("recplay", "stop")); LL_INFOS("Voice") << "Playing voice buffer" << LL_ENDL; @@ -2924,11 +2918,9 @@ void LLVivoxVoiceClient::sessionCreateResponse(std::string &requestId, int statu session->mErrorStatusString = statusString; if(session == mAudioSession) { - LLSD vivoxevent = LLSD::emptyMap(); - - vivoxevent["handle"] = LLSD::String(sessionHandle); - vivoxevent["session"] = LLSD::String("failed"); - vivoxevent["reason"] = LLSD::Integer(statusCode); + LLSD vivoxevent(LLSDMap("handle", LLSD::String(sessionHandle)) + ("session", "failed") + ("reason", LLSD::Integer(statusCode))); LLEventPumps::instance().post("vivoxClientPump", vivoxevent); } @@ -2945,10 +2937,8 @@ void LLVivoxVoiceClient::sessionCreateResponse(std::string &requestId, int statu { setSessionHandle(session, sessionHandle); } - LLSD vivoxevent = LLSD::emptyMap(); - - vivoxevent["handle"] = LLSD::String(sessionHandle); - vivoxevent["session"] = LLSD::String("created"); + LLSD vivoxevent(LLSDMap("handle", LLSD::String(sessionHandle)) + ("session", "created")); LLEventPumps::instance().post("vivoxClientPump", vivoxevent); } @@ -2972,10 +2962,8 @@ void LLVivoxVoiceClient::sessionGroupAddSessionResponse(std::string &requestId, session->mErrorStatusString = statusString; if(session == mAudioSession) { - LLSD vivoxevent = LLSD::emptyMap(); - - vivoxevent["handle"] = LLSD::String(sessionHandle); - vivoxevent["session"] = LLSD::String("failed"); + LLSD vivoxevent(LLSDMap("handle", LLSD::String(sessionHandle)) + ("session", "failed")); LLEventPumps::instance().post("vivoxClientPump", vivoxevent); } @@ -2993,10 +2981,8 @@ void LLVivoxVoiceClient::sessionGroupAddSessionResponse(std::string &requestId, setSessionHandle(session, sessionHandle); } - LLSD vivoxevent = LLSD::emptyMap(); - - vivoxevent["handle"] = LLSD::String(sessionHandle); - vivoxevent["session"] = LLSD::String("added"); + LLSD vivoxevent(LLSDMap("handle", LLSD::String(sessionHandle)) + ("session", "added")); LLEventPumps::instance().post("vivoxClientPump", vivoxevent); @@ -3041,9 +3027,7 @@ void LLVivoxVoiceClient::logoutResponse(int statusCode, std::string &statusStrin LL_WARNS("Voice") << "Account.Logout response failure: " << statusString << LL_ENDL; // Should this ever fail? do we care if it does? } - LLSD vivoxevent = LLSD::emptyMap(); - - vivoxevent["logout"] = LLSD::Boolean(true); + LLSD vivoxevent(LLSDMap("logout", LLSD::Boolean(true))); LLEventPumps::instance().post("vivoxClientPump", vivoxevent); } @@ -3058,9 +3042,7 @@ void LLVivoxVoiceClient::connectorShutdownResponse(int statusCode, std::string & mConnected = false; - LLSD vivoxevent = LLSD::emptyMap(); - - vivoxevent["connector"] = LLSD::Boolean(false); + LLSD vivoxevent(LLSDMap("connector", LLSD::Boolean(false))); LLEventPumps::instance().post("vivoxClientPump", vivoxevent); } @@ -3168,10 +3150,8 @@ void LLVivoxVoiceClient::joinedAudioSession(const sessionStatePtr_t &session) // This is the session we're joining. if(mIsJoiningSession) { - LLSD vivoxevent = LLSD::emptyMap(); - - vivoxevent["handle"] = LLSD::String(session->mHandle); - vivoxevent["session"] = LLSD::String("joined"); + LLSD vivoxevent(LLSDMap("handle", LLSD::String(session->mHandle)) + ("session", "joined")); LLEventPumps::instance().post("vivoxClientPump", vivoxevent); @@ -3314,10 +3294,8 @@ void LLVivoxVoiceClient::leftAudioSession(const sessionStatePtr_t &session) { if (mAudioSession == session) { - LLSD vivoxevent = LLSD::emptyMap(); - - vivoxevent["handle"] = LLSD::String(session->mHandle); - vivoxevent["session"] = LLSD::String("removed"); + LLSD vivoxevent(LLSDMap("handle", LLSD::String(session->mHandle)) + ("session", "removed")); LLEventPumps::instance().post("vivoxClientPump", vivoxevent); } @@ -6172,9 +6150,7 @@ void LLVivoxVoiceClient::accountGetSessionFontsResponse(int statusCode, const st { // *TODO: We seem to get multiple events of this type. Should figure a way to advance only after // receiving the last one. - LLSD result = LLSD::emptyMap(); - - result["voice_fonts"] = LLSD::Boolean(true); + LLSD result(LLSDMap("voice_fonts", LLSD::Boolean(true))); LLEventPumps::instance().post("vivoxClientPump", result); } @@ -6347,8 +6323,7 @@ void LLVivoxVoiceClient::recordPreviewBuffer() mCaptureBufferRecording = true; - LLSD result; - result["recplay"] = "record"; + LLSD result(LLSDMap("recplay", "record")); LLEventPumps::instance().post("vivoxClientPump", result); } @@ -6371,8 +6346,7 @@ void LLVivoxVoiceClient::playPreviewBuffer(const LLUUID& effect_id) mPreviewVoiceFont = effect_id; mCaptureBufferPlaying = true; - LLSD result; - result["recplay"] = "playback"; + LLSD result(LLSDMap("recplay", "playback")); LLEventPumps::instance().post("vivoxClientPump", result); } @@ -6381,8 +6355,7 @@ void LLVivoxVoiceClient::stopPreviewBuffer() mCaptureBufferRecording = false; mCaptureBufferPlaying = false; - LLSD result; - result["recplay"] = "quit"; + LLSD result(LLSDMap("recplay", "quit")); LLEventPumps::instance().post("vivoxClientPump", result); } -- cgit v1.2.3 From 66dd72459ae5ad17bfab622c71b2122233707dd4 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Tue, 26 Apr 2016 13:44:44 -0700 Subject: MAINT-6336: Initialize TempBoundListener with constructor --- indra/llcommon/lleventcoro.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp index c8c43dc334..2d5f964deb 100755 --- a/indra/llcommon/lleventcoro.cpp +++ b/indra/llcommon/lleventcoro.cpp @@ -244,8 +244,8 @@ LLSD llcoro::suspendUntilEventOnWithTimeout(const LLEventPumpOrPumpName& suspend LLEventTimeout timeoutPump; LLEventPump &suspendPump = suspendPumpOrName.getPump(); - LLTempBoundListener timeoutListener = timeoutPump.listen(suspendPump.getName(), - boost::bind(&LLEventPump::post, &suspendPump, _1)); + LLTempBoundListener timeoutListener(timeoutPump.listen(suspendPump.getName(), + boost::bind(&LLEventPump::post, &suspendPump, _1))); timeoutPump.eventAfter(timeoutin, timeoutResult); return llcoro::suspendUntilEventOn(suspendPump); -- cgit v1.2.3