summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llcommon/llevents.cpp102
-rw-r--r--indra/llcommon/llevents.h39
-rw-r--r--indra/llcommon/llleaplistener.cpp21
-rw-r--r--indra/test/llevents_tut.cpp57
4 files changed, 46 insertions, 173 deletions
diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp
index 186e710c43..d31f5f2d32 100644
--- a/indra/llcommon/llevents.cpp
+++ b/indra/llcommon/llevents.cpp
@@ -64,51 +64,16 @@
#endif
/*****************************************************************************
-* queue_names: specify LLEventPump names that should be instantiated as
-* LLEventQueue
-*****************************************************************************/
-/**
- * At present, we recognize particular requested LLEventPump names as needing
- * LLEventQueues. Later on we'll migrate this information to an external
- * configuration file.
- */
-const char* queue_names[] =
-{
- "placeholder - replace with first real name string"
-};
-
-/*****************************************************************************
-* If there's a "mainloop" pump, listen on that to flush all LLEventQueues
+* LLEventPumps
*****************************************************************************/
-struct RegisterFlush : public LLEventTrackable
+LLEventPumps::PumpFactories LLEventPumps::mFactories
{
- RegisterFlush():
- pumps(LLEventPumps::instance())
- {
- pumps.obtain("mainloop").listen("flushLLEventQueues", boost::bind(&RegisterFlush::flush, this, _1));
- }
- bool flush(const LLSD&)
- {
- pumps.flush();
- return false;
- }
- ~RegisterFlush()
- {
- // LLEventTrackable handles stopListening for us.
- }
- LLEventPumps& pumps;
+ // LLEventStream is the default for obtain(), so even if somebody DOES
+ // call obtain("placeholder"), this sample entry won't break anything.
+ { "placeholder", [](const std::string& name) { return new LLEventStream(name); } }
};
-static RegisterFlush registerFlush;
-/*****************************************************************************
-* LLEventPumps
-*****************************************************************************/
-LLEventPumps::LLEventPumps():
- // Until we migrate this information to an external config file,
- // initialize mQueueNames from the static queue_names array.
- mQueueNames(boost::begin(queue_names), boost::end(queue_names))
-{
-}
+LLEventPumps::LLEventPumps() {}
LLEventPump& LLEventPumps::obtain(const std::string& name)
{
@@ -121,10 +86,10 @@ LLEventPump& LLEventPumps::obtain(const std::string& name)
}
// Here we must instantiate an LLEventPump subclass.
LLEventPump* newInstance;
- // Should this name be an LLEventQueue?
- PumpNames::const_iterator nfound = mQueueNames.find(name);
- if (nfound != mQueueNames.end())
- newInstance = new LLEventQueue(name);
+ // Do we have a predefined factory for this instance name?
+ PumpFactories::const_iterator nfound = mFactories.find(name);
+ if (nfound != mFactories.end())
+ newInstance = (nfound->second)(name);
else
newInstance = new LLEventStream(name);
// LLEventPump's constructor implicitly registers each new instance in
@@ -144,14 +109,13 @@ bool LLEventPumps::post(const std::string&name, const LLSD&message)
return (*found).second->post(message);
}
-
void LLEventPumps::flush()
{
// Flush every known LLEventPump instance. Leave it up to each instance to
// decide what to do with the flush() call.
- for (PumpMap::iterator pmi = mPumpMap.begin(), pmend = mPumpMap.end(); pmi != pmend; ++pmi)
+ for (PumpMap::value_type& pair : mPumpMap)
{
- pmi->second->flush();
+ pair.second->flush();
}
}
@@ -605,48 +569,6 @@ LLBoundListener LLEventMailDrop::listen_impl(const std::string& name,
void LLEventMailDrop::discard()
{
mEventHistory.clear();
- LLEventStream::flush();
-}
-
-/*****************************************************************************
-* LLEventQueue
-*****************************************************************************/
-bool LLEventQueue::post(const LLSD& event)
-{
- if (mEnabled)
- {
- // Defer sending this event by queueing it until flush()
- mEventQueue.push_back(event);
- }
- // Unconditionally return false. We won't know until flush() whether a
- // listener claims to have handled the event -- meanwhile, don't block
- // other listeners.
- return false;
-}
-
-void LLEventQueue::flush()
-{
- if(!mSignal) return;
-
- // Consider the case when a given listener on this LLEventQueue posts yet
- // another event on the same queue. If we loop over mEventQueue directly,
- // we'll end up processing all those events during the same flush() call
- // -- rather like an EventStream. Instead, copy mEventQueue and clear it,
- // so that any new events posted to this LLEventQueue during flush() will
- // be processed in the *next* flush() call.
- EventQueue queue(mEventQueue);
- mEventQueue.clear();
- // NOTE NOTE NOTE: Any new access to member data beyond this point should
- // cause us to move our LLStandardSignal object to a pimpl class along
- // with said member data. Then the local shared_ptr will preserve both.
-
- // DEV-43463: capture a local copy of mSignal. See LLEventStream::post()
- // for detailed comments.
- boost::shared_ptr<LLStandardSignal> signal(mSignal);
- for ( ; ! queue.empty(); queue.pop_front())
- {
- (*signal)(queue.front());
- }
}
/*****************************************************************************
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
index ce2aa2f3c9..c55351919e 100644
--- a/indra/llcommon/llevents.h
+++ b/indra/llcommon/llevents.h
@@ -37,6 +37,7 @@
#include <set>
#include <vector>
#include <deque>
+#include <functional>
#if LL_WINDOWS
#pragma warning (push)
#pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
@@ -55,7 +56,6 @@
#include <boost/visit_each.hpp>
#include <boost/ref.hpp> // reference_wrapper
#include <boost/type_traits/is_pointer.hpp>
-#include <boost/function.hpp>
#include <boost/static_assert.hpp>
#include "llsd.h"
#include "llsingleton.h"
@@ -303,10 +303,10 @@ testable:
// destroyed.
typedef std::set<LLEventPump*> PumpSet;
PumpSet mOurPumps;
- // LLEventPump names that should be instantiated as LLEventQueue rather
- // than as LLEventStream
- typedef std::set<std::string> PumpNames;
- PumpNames mQueueNames;
+ // LLEventPump subclasses that should be instantiated for particular
+ // instance names
+ typedef std::map<std::string, std::function<LLEventPump*(const std::string&)>> PumpFactories;
+ static PumpFactories mFactories;
};
/*****************************************************************************
@@ -351,7 +351,7 @@ typedef boost::signals2::trackable LLEventTrackable;
*****************************************************************************/
/**
* LLEventPump is the base class interface through which we access the
- * concrete subclasses LLEventStream and LLEventQueue.
+ * concrete subclasses such as LLEventStream.
*
* @NOTE
* LLEventPump derives from LLEventTrackable so that when you "chain"
@@ -594,11 +594,10 @@ public:
* event *must* eventually reach a listener that will consume it, else the
* queue will grow to arbitrary length.
*
- * @NOTE: When using an LLEventMailDrop (or LLEventQueue) with a LLEventTimeout or
+ * @NOTE: When using an LLEventMailDrop with an LLEventTimeout or
* LLEventFilter attaching the filter downstream, using Timeout's constructor will
* cause the MailDrop to discharge any of its 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
{
@@ -623,30 +622,6 @@ private:
};
/*****************************************************************************
-* LLEventQueue
-*****************************************************************************/
-/**
- * LLEventQueue is a LLEventPump whose post() method defers calling registered
- * listeners until flush() is called.
- */
-class LL_COMMON_API LLEventQueue: public LLEventPump
-{
-public:
- LLEventQueue(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
- virtual ~LLEventQueue() {}
-
- /// Post an event to all listeners
- virtual bool post(const LLSD& event);
-
- /// flush queued events
- virtual void flush();
-
-private:
- typedef std::deque<LLSD> EventQueue;
- EventQueue mEventQueue;
-};
-
-/*****************************************************************************
* LLReqID
*****************************************************************************/
/**
diff --git a/indra/llcommon/llleaplistener.cpp b/indra/llcommon/llleaplistener.cpp
index f50bacb1e8..0d18e5fff9 100644
--- a/indra/llcommon/llleaplistener.cpp
+++ b/indra/llcommon/llleaplistener.cpp
@@ -14,6 +14,8 @@
// associated header
#include "llleaplistener.h"
// STL headers
+#include <map>
+#include <functional>
// std headers
// external library headers
#include <boost/foreach.hpp>
@@ -119,6 +121,18 @@ LLLeapListener::~LLLeapListener()
}
}
+namespace
+{
+
+static std::map<std::string, std::function<LLEventPump*(const std::string&)>> factories
+{
+ // tweak name for uniqueness
+ { "LLEventStream", [](const std::string& name){ return new LLEventStream(name, true); } },
+ { "LLEventMailDrop", [](const std::string& name){ return new LLEventMailDrop(name, true); } }
+};
+
+} // anonymous namespace
+
void LLLeapListener::newpump(const LLSD& request)
{
Response reply(LLSD(), request);
@@ -127,13 +141,14 @@ void LLLeapListener::newpump(const LLSD& request)
LLSD const & type = request["type"];
LLEventPump * new_pump = NULL;
- if (type.asString() == "LLEventQueue")
+ auto found = factories.find(type.asString());
+ if (found != factories.end())
{
- new_pump = new LLEventQueue(name, true); // tweak name for uniqueness
+ new_pump = (found->second)(name);
}
else
{
- if (! (type.isUndefined() || type.asString() == "LLEventStream"))
+ if (! type.isUndefined())
{
reply.warn(STRINGIZE("unknown 'type' " << type << ", using LLEventStream"));
}
diff --git a/indra/test/llevents_tut.cpp b/indra/test/llevents_tut.cpp
index a8a3188249..17f64a4953 100644
--- a/indra/test/llevents_tut.cpp
+++ b/indra/test/llevents_tut.cpp
@@ -91,9 +91,7 @@ template<> template<>
void events_object::test<1>()
{
set_test_name("basic operations");
- // Now there's a static constructor in llevents.cpp that registers on
- // the "mainloop" pump to call LLEventPumps::flush().
- // Actually -- having to modify this to track the statically-
+ // Having to modify this to track the statically-
// constructed pumps in other TUT modules in this giant monolithic test
// executable isn't such a hot idea.
// ensure_equals("initial pump", pumps.mPumpMap.size(), 1);
@@ -210,43 +208,6 @@ bool chainEvents(Listener& someListener, const LLSD& event)
template<> template<>
void events_object::test<3>()
{
- set_test_name("LLEventQueue delayed action");
- // This access is NOT legal usage: we can do it only because we're
- // hacking private for test purposes. Normally we'd either compile in
- // a particular name, or (later) edit a config file.
- pumps.mQueueNames.insert("login");
- LLEventPump& login(pumps.obtain("login"));
- // The "mainloop" pump is special: posting on that implicitly calls
- // LLEventPumps::flush(), which in turn should flush our "login"
- // LLEventQueue.
- LLEventPump& mainloop(pumps.obtain("mainloop"));
- ensure("LLEventQueue leaf class", dynamic_cast<LLEventQueue*> (&login));
- listener0.listenTo(login);
- listener0.reset(0);
- login.post(1);
- check_listener("waiting for queued event", listener0, 0);
- mainloop.post(LLSD());
- check_listener("got queued event", listener0, 1);
- login.stopListening(listener0.getName());
- // Verify that when an event handler posts a new event on the same
- // LLEventQueue, it doesn't get processed in the same flush() call --
- // it waits until the next flush() call.
- listener0.reset(17);
- login.listen("chainEvents", boost::bind(chainEvents, boost::ref(listener0), _1));
- login.post(1);
- check_listener("chainEvents(1) not yet called", listener0, 17);
- mainloop.post(LLSD());
- check_listener("chainEvents(1) called", listener0, 1);
- mainloop.post(LLSD());
- check_listener("chainEvents(0) called", listener0, 0);
- mainloop.post(LLSD());
- check_listener("chainEvents(-1) not called", listener0, 0);
- login.stopListening("chainEvents");
-}
-
-template<> template<>
-void events_object::test<4>()
-{
set_test_name("explicitly-instantiated LLEventStream");
// Explicitly instantiate an LLEventStream, and verify that it
// self-registers with LLEventPumps
@@ -270,7 +231,7 @@ void events_object::test<4>()
}
template<> template<>
-void events_object::test<5>()
+void events_object::test<4>()
{
set_test_name("stopListening()");
LLEventPump& login(pumps.obtain("login"));
@@ -284,7 +245,7 @@ void events_object::test<5>()
}
template<> template<>
-void events_object::test<6>()
+void events_object::test<5>()
{
set_test_name("chaining LLEventPump instances");
LLEventPump& upstream(pumps.obtain("upstream"));
@@ -309,7 +270,7 @@ void events_object::test<6>()
}
template<> template<>
-void events_object::test<7>()
+void events_object::test<6>()
{
set_test_name("listener dependency order");
typedef LLEventPump::NameList NameList;
@@ -391,7 +352,7 @@ void events_object::test<7>()
}
template<> template<>
-void events_object::test<8>()
+void events_object::test<7>()
{
set_test_name("tweaked and untweaked LLEventPump instance names");
{ // nested scope
@@ -423,7 +384,7 @@ void eventSource(const LLListenerOrPumpName& listener)
}
template<> template<>
-void events_object::test<9>()
+void events_object::test<8>()
{
set_test_name("LLListenerOrPumpName");
// Passing a boost::bind() expression to LLListenerOrPumpName
@@ -464,7 +425,7 @@ private:
};
template<> template<>
-void events_object::test<10>()
+void events_object::test<9>()
{
set_test_name("listen(boost::bind(...TempListener...))");
// listen() can't do anything about a plain TempListener instance:
@@ -501,7 +462,7 @@ public:
};
template<> template<>
-void events_object::test<11>()
+void events_object::test<10>()
{
set_test_name("listen(boost::bind(...TempTrackableListener ref...))");
bool live = false;
@@ -524,7 +485,7 @@ void events_object::test<11>()
}
template<> template<>
-void events_object::test<12>()
+void events_object::test<11>()
{
set_test_name("listen(boost::bind(...TempTrackableListener pointer...))");
bool live = false;