diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index c2fa79a524f12e158bec85b878f2da48ddacd6d2..aec9acc7eff4b19565772dc17dcea8d24c47b7c8 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -59,14 +59,12 @@ const char* queue_names[] = /***************************************************************************** * If there's a "mainloop" pump, listen on that to flush all LLEventQueues *****************************************************************************/ -struct RegisterFlush +struct RegisterFlush : public LLEventTrackable { RegisterFlush(): - pumps(LLEventPumps::instance()), - mainloop(pumps.obtain("mainloop")), - name("flushLLEventQueues") + pumps(LLEventPumps::instance()) { - mainloop.listen(name, boost::bind(&RegisterFlush::flush, this, _1)); + pumps.obtain("mainloop").listen("flushLLEventQueues", boost::bind(&RegisterFlush::flush, this, _1)); } bool flush(const LLSD&) { @@ -75,11 +73,9 @@ struct RegisterFlush } ~RegisterFlush() { - mainloop.stopListening(name); + // LLEventTrackable handles stopListening for us. } LLEventPumps& pumps; - LLEventPump& mainloop; - const std::string name; }; static RegisterFlush registerFlush; diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp index 62988cdc644ae67528debf91b2b44f1cbf1e62bd..6b5feaf1c46a0553cab0e65f6a9ef6672fc54bde 100644 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -34,5 +34,5 @@ #include "llsingleton.h" -std::map<std::string, void *> LLSingletonRegistry::sSingletonMap; +std::map<std::string, void *> * LLSingletonRegistry::sSingletonMap = NULL; diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 00c87821c2449e251ed47fbdc50acdd04bf33231..f55fafadd8dff8ea44e9b41eec191d86879a9053 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -42,19 +42,30 @@ class LL_COMMON_API LLSingletonRegistry { private: typedef std::map<std::string, void *> TypeMap; - static TypeMap sSingletonMap; + static TypeMap * sSingletonMap; + + static void checkInit() + { + if(sSingletonMap == NULL) + { + sSingletonMap = new TypeMap(); + } + } public: template<typename T> static void * & get() { std::string name(typeid(T).name()); - if(0 == sSingletonMap.count(name)) - { - sSingletonMap[name] = NULL; - } + checkInit(); + + // the first entry of the pair returned by insert will be either the existing + // iterator matching our key, or the newly inserted NULL initialized entry + // see "Insert element" in http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html + TypeMap::iterator result = + sSingletonMap->insert(std::make_pair(name, (void*)NULL)).first; - return sSingletonMap[typeid(T).name()]; + return result->second; } }; @@ -130,12 +141,13 @@ class LLSingleton : private boost::noncopyable static SingletonInstanceData& getData() { - void * & registry = LLSingletonRegistry::get<DERIVED_TYPE>(); - static SingletonInstanceData data; + // this is static to cache the lookup results + static void * & registry = LLSingletonRegistry::get<DERIVED_TYPE>(); // *TODO - look into making this threadsafe if(NULL == registry) { + static SingletonInstanceData data; registry = &data; } diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index 9859d3428441d6a8362bccab271125de06f37f72..e43c3ecde7fe074ac8d40b017808d3d9345c525e 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -52,12 +52,12 @@ #include "message.h" -LLFloaterTOS::LLFloaterTOS(const LLSD& message) -: LLModalDialog( message, 100, 100 ), - mMessage(message.asString()), +LLFloaterTOS::LLFloaterTOS(const LLSD& data) +: LLModalDialog( data["message"].asString(), 100, 100 ), + mMessage(data["message"].asString()), mWebBrowserWindowId( 0 ), mLoadCompleteCount( 0 ), - mCallback() + mReplyPumpName(data["reply_pump"].asString()) { } @@ -205,9 +205,9 @@ void LLFloaterTOS::onContinue( void* userdata ) LLFloaterTOS* self = (LLFloaterTOS*) userdata; llinfos << "User agrees with TOS." << llendl; - if(self->mCallback) + if(self->mReplyPumpName != "") { - self->mCallback(true); + LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD(true)); } self->closeFloater(); // destroys this object @@ -219,9 +219,9 @@ void LLFloaterTOS::onCancel( void* userdata ) LLFloaterTOS* self = (LLFloaterTOS*) userdata; llinfos << "User disagrees with TOS." << llendl; - if(self->mCallback) + if(self->mReplyPumpName != "") { - self->mCallback(false); + LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD(false)); } self->mLoadCompleteCount = 0; // reset counter for next time we come to TOS @@ -241,7 +241,3 @@ void LLFloaterTOS::onNavigateComplete( const EventType& eventIn ) }; } -void LLFloaterTOS::setTOSCallback(LLFloaterTOS::YesNoCallback const & callback) -{ - mCallback = callback; -} diff --git a/indra/newview/llfloatertos.h b/indra/newview/llfloatertos.h index 0b15c24bc8d019b4c54f54106e81080c2a4adc30..89ad29170c0eb31c925827208850d20170a5edf9 100644 --- a/indra/newview/llfloatertos.h +++ b/indra/newview/llfloatertos.h @@ -49,11 +49,9 @@ class LLFloaterTOS : public LLWebBrowserCtrlObserver { public: - LLFloaterTOS(const LLSD& message); + LLFloaterTOS(const LLSD& data); virtual ~LLFloaterTOS(); - typedef boost::function<void(bool)> YesNoCallback; - BOOL postBuild(); virtual void draw(); @@ -66,14 +64,11 @@ class LLFloaterTOS : virtual void onNavigateComplete( const EventType& eventIn ); - // *TODO - consider getting rid of this in favor of using an event pump. -brad - void setTOSCallback(YesNoCallback const & callback); - private: std::string mMessage; int mWebBrowserWindowId; int mLoadCompleteCount; - YesNoCallback mCallback; + std::string mReplyPumpName; }; #endif // LL_LLFLOATERTOS_H diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 3c59cb83cdd080810a8e3d6f723de2d9eb0b3a8d..cb7dbc2de0f385e66809313b8a7e7cfaf44ef45b 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -56,6 +56,9 @@ #include "lltrans.h" #endif +static const char * const TOS_REPLY_PUMP = "lllogininstance_tos_callback"; +static const char * const TOS_LISTENER_NAME = "lllogininstance_tos"; + std::string construct_start_string(); LLLoginInstance::LLLoginInstance() : @@ -222,19 +225,25 @@ bool LLLoginInstance::handleLoginFailure(const LLSD& event) // to reconnect or to end the attempt in failure. if(reason_response == "tos") { - LLFloaterTOS * tos = - LLFloaterReg::showTypedInstance<LLFloaterTOS>("message_tos", LLSD(message_response)); - - tos->setTOSCallback(boost::bind(&LLLoginInstance::handleTOSResponse, - this, _1, "agree_to_tos")); + LLSD data(LLSD::emptyMap()); + data["message"] = message_response; + data["reply_pump"] = TOS_REPLY_PUMP; + LLFloaterReg::showInstance("message_tos", data); + LLEventPumps::instance().obtain(TOS_REPLY_PUMP) + .listen(TOS_LISTENER_NAME, + boost::bind(&LLLoginInstance::handleTOSResponse, + this, _1, "agree_to_tos")); } else if(reason_response == "critical") { - LLFloaterTOS * tos = - LLFloaterReg::showTypedInstance<LLFloaterTOS>("message_critical",LLSD(message_response)); - - tos->setTOSCallback(boost::bind(&LLLoginInstance::handleTOSResponse, - this, _1, "read_critical")); + LLSD data(LLSD::emptyMap()); + data["message"] = message_response; + data["reply_pump"] = TOS_REPLY_PUMP; + LLFloaterReg::showInstance("message_critical", data); + LLEventPumps::instance().obtain(TOS_REPLY_PUMP) + .listen(TOS_LISTENER_NAME, + boost::bind(&LLLoginInstance::handleTOSResponse, + this, _1, "read_critical")); } else if(reason_response == "update" || gSavedSettings.getBOOL("ForceMandatoryUpdate")) { @@ -279,7 +288,7 @@ bool LLLoginInstance::handleLoginSuccess(const LLSD& event) return false; } -void LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) +bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) { if(accepted) { @@ -291,6 +300,9 @@ void LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) { attemptComplete(); } + + LLEventPumps::instance().obtain(TOS_REPLY_PUMP).stopListening(TOS_LISTENER_NAME); + return true; } @@ -453,3 +465,4 @@ std::string construct_start_string() } return start; } + diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index 47d52a6184b0630b4ac5ef4ef365866725c6a0b5..6a2ccf919e3c2e5fa0e0a28697d4e44f0c077df6 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -88,7 +88,7 @@ class LLLoginInstance : public LLSingleton<LLLoginInstance> bool handleLoginFailure(const LLSD& event); bool handleLoginSuccess(const LLSD& event); - void handleTOSResponse(bool v, const std::string& key); + bool handleTOSResponse(bool v, const std::string& key); void attemptComplete() { mAttemptComplete = true; } // In the future an event? diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index d3080d6e4a3d61fc8f04fe79950980fe3062ae11..a84e79615907bbb5b89e41ddf2de08f0b11f390a 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -91,23 +91,16 @@ LLURLSimString LLURLSimString::sInstance; bool LLURLSimString::parse() { return true; } //----------------------------------------------------------------------------- -#include "llfloaterreg.h" #include "../llfloatertos.h" +#include "llfloaterreg.h" static std::string gTOSType; -static LLFloaterTOS::YesNoCallback gTOSCallback; - -void LLFloaterTOS::setTOSCallback(YesNoCallback const & callback) -{ - gTOSCallback = callback; -} +static LLEventPump * gTOSReplyPump = NULL; //static -LLFloater* LLFloaterReg::showInstance(const std::string & name, - const LLSD & key, - BOOL focus) +LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus) { gTOSType = name; - gTOSCallback = LLFloaterTOS::YesNoCallback(); + gTOSReplyPump = &LLEventPumps::instance().obtain(key["reply_pump"]); return NULL; } @@ -191,7 +184,7 @@ namespace tut gDisconnectCalled = false; gTOSType = ""; // Set to invalid value. - gTOSCallback = 0; // clear the callback. + gTOSReplyPump = 0; // clear the callback. gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", FALSE); @@ -280,14 +273,14 @@ namespace tut gTestPump.post(response); ensure_equals("TOS Dialog type", gTOSType, "message_tos"); - ensure("TOS callback given", gTOSCallback != 0); - gTOSCallback(false); // Call callback denying TOS. + ensure("TOS callback given", gTOSReplyPump != 0); + gTOSReplyPump->post(false); // Call callback denying TOS. ensure("No TOS, failed auth", logininstance->authFailure()); // Start again. logininstance->connect(test_uri, credentials); gTestPump.post(response); // Fail for tos again. - gTOSCallback(true); // Accept tos, should reconnect w/ agree_to_tos. + gTOSReplyPump->post(true); // Accept tos, should reconnect w/ agree_to_tos. ensure_equals("Accepted agree to tos", gLoginCreds["params"]["agree_to_tos"].asBoolean(), true); ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess()); @@ -306,8 +299,8 @@ namespace tut gTestPump.post(response); ensure_equals("TOS Dialog type", gTOSType, "message_critical"); - ensure("TOS callback given", gTOSCallback != 0); - gTOSCallback(true); + ensure("TOS callback given", gTOSReplyPump != 0); + gTOSReplyPump->post(true); ensure_equals("Accepted read critical message", gLoginCreds["params"]["read_critical"].asBoolean(), true); ensure("Incomplete login status", !logininstance->authFailure() && !logininstance->authSuccess());