summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRider Linden <rider@lindenlab.com>2016-04-26 11:56:25 -0700
committerRider Linden <rider@lindenlab.com>2016-04-26 11:56:25 -0700
commitdd2311b993d137c538ca57b4360669db6d7fbfa0 (patch)
treee7b3553da33dedfd436192e6ae555d884e58ce16
parent4d9dd3271b1a015d9afd21767e579a4cd71982ed (diff)
MAINT-6336: Put the timeout upstream of the suspending pump and fire the timeout it. Also some cleanup on LLSD construction in vivox.
-rwxr-xr-xindra/llcommon/lleventcoro.cpp21
-rwxr-xr-xindra/llcommon/lleventcoro.h5
-rwxr-xr-xindra/llcommon/lleventfilter.h14
-rwxr-xr-xindra/llcommon/llevents.h6
-rwxr-xr-xindra/newview/llvoicevivox.cpp77
5 files changed, 65 insertions, 58 deletions
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);
}