summaryrefslogtreecommitdiff
path: root/indra/llcommon/lleventfilter.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/lleventfilter.h')
-rw-r--r--indra/llcommon/lleventfilter.h162
1 files changed, 162 insertions, 0 deletions
diff --git a/indra/llcommon/lleventfilter.h b/indra/llcommon/lleventfilter.h
index ff8fc9bc7f..48c2570732 100644
--- a/indra/llcommon/lleventfilter.h
+++ b/indra/llcommon/lleventfilter.h
@@ -32,8 +32,12 @@
#include "llevents.h"
#include "stdtypes.h"
#include "lltimer.h"
+#include "llsdutil.h"
#include <boost/function.hpp>
+class LLEventTimer;
+class LLDate;
+
/**
* Generic base class
*/
@@ -210,6 +214,19 @@ public:
LLEventTimeout();
LLEventTimeout(LLEventPump& source);
+ /// using LLEventTimeout as namespace for free functions
+ /// Post event to specified LLEventPump every period seconds. Delete
+ /// returned LLEventTimer* to cancel.
+ static LLEventTimer* post_every(F32 period, const std::string& pump, const LLSD& data);
+ /// Post event to specified LLEventPump at specified future time. Call
+ /// LLEventTimer::getInstance(returned pointer) to check whether it's still
+ /// pending; if so, delete the pointer to cancel.
+ static LLEventTimer* post_at(const LLDate& time, const std::string& pump, const LLSD& data);
+ /// Post event to specified LLEventPump after specified interval. Call
+ /// LLEventTimer::getInstance(returned pointer) to check whether it's still
+ /// pending; if so, delete the pointer to cancel.
+ static LLEventTimer* post_after(F32 interval, const std::string& pump, const LLSD& data);
+
protected:
virtual void setCountdown(F32 seconds);
virtual bool countdownElapsed() const;
@@ -376,4 +393,149 @@ private:
std::size_t mBatchSize;
};
+/**
+ * LLStoreListener self-registers on the LLEventPump of interest, and
+ * unregisters on destruction. As long as it exists, a particular element is
+ * extracted from every event that comes through the upstream LLEventPump and
+ * stored into the target variable.
+ *
+ * This is implemented as a subclass of LLEventFilter, though strictly
+ * speaking it isn't really a "filter" at all: it never passes incoming events
+ * to its own listeners, if any.
+ *
+ * TBD: A variant based on output iterators that stores and then increments
+ * the iterator. Useful with boost::coroutine2!
+ */
+template <typename T>
+class LLStoreListener: public LLEventFilter
+{
+public:
+ // pass target and optional path to element
+ LLStoreListener(T& target, const LLSD& path=LLSD(), bool consume=false):
+ LLEventFilter("store"),
+ mTarget(target),
+ mPath(path),
+ mConsume(consume)
+ {}
+ // construct and connect
+ LLStoreListener(LLEventPump& source, T& target, const LLSD& path=LLSD(), bool consume=false):
+ LLEventFilter(source, "store"),
+ mTarget(target),
+ mPath(path),
+ mConsume(consume)
+ {}
+
+ // Calling post() with an LLSD event extracts the element indicated by
+ // path, then stores it to mTarget.
+ virtual bool post(const LLSD& event)
+ {
+ // Extract the element specified by 'mPath' from 'event'. To perform a
+ // generic type-appropriate store through mTarget, construct an
+ // LLSDParam<T> and store that, thus engaging LLSDParam's custom
+ // conversions.
+ mTarget = LLSDParam<T>(llsd::drill(event, mPath));
+ return mConsume;
+ }
+
+private:
+ T& mTarget;
+ const LLSD mPath;
+ const bool mConsume;
+};
+
+/*****************************************************************************
+* LLEventLogProxy
+*****************************************************************************/
+/**
+ * LLEventLogProxy is a little different than the other LLEventFilter
+ * subclasses declared in this header file, in that it completely wraps the
+ * passed LLEventPump (both input and output) instead of simply processing its
+ * output. Of course, if someone directly posts to the wrapped LLEventPump by
+ * looking up its string name in LLEventPumps, LLEventLogProxy can't intercept
+ * that post() call. But as long as consuming code is willing to access the
+ * LLEventLogProxy instance instead of the wrapped LLEventPump, all event data
+ * both post()ed and received is logged.
+ *
+ * The proxy role means that LLEventLogProxy intercepts more of LLEventPump's
+ * API than a typical LLEventFilter subclass.
+ */
+class LLEventLogProxy: public LLEventFilter
+{
+ typedef LLEventFilter super;
+public:
+ /**
+ * Construct LLEventLogProxy, wrapping the specified LLEventPump.
+ * Unlike a typical LLEventFilter subclass, the name parameter is @emph
+ * not optional because typically you want LLEventLogProxy to completely
+ * replace the wrapped LLEventPump. So you give the subject LLEventPump
+ * some other name and give the LLEventLogProxy the name that would have
+ * been used for the subject LLEventPump.
+ */
+ LLEventLogProxy(LLEventPump& source, const std::string& name, bool tweak=false);
+
+ /// register a new listener
+ LLBoundListener listen_impl(const std::string& name, const LLEventListener& target,
+ const NameList& after, const NameList& before);
+
+ /// Post an event to all listeners
+ virtual bool post(const LLSD& event) /* override */;
+
+private:
+ /// This method intercepts each call to any target listener. We pass it
+ /// the listener name and the caller's intended target listener plus the
+ /// posted LLSD event.
+ bool listener(const std::string& name,
+ const LLEventListener& target,
+ const LLSD& event) const;
+
+ LLEventPump& mPump;
+ LLSD::Integer mCounter{0};
+};
+
+/**
+ * LLEventPumpHolder<T> is a helper for LLEventLogProxyFor<T>. It simply
+ * stores an instance of T, presumably a subclass of LLEventPump. We derive
+ * LLEventLogProxyFor<T> from LLEventPumpHolder<T>, ensuring that
+ * LLEventPumpHolder's contained mWrappedPump is fully constructed before
+ * passing it to LLEventLogProxyFor's LLEventLogProxy base class constructor.
+ * But since LLEventPumpHolder<T> presents none of the LLEventPump API,
+ * LLEventLogProxyFor<T> inherits its methods unambiguously from
+ * LLEventLogProxy.
+ */
+template <class T>
+class LLEventPumpHolder
+{
+protected:
+ LLEventPumpHolder(const std::string& name, bool tweak=false):
+ mWrappedPump(name, tweak)
+ {}
+ T mWrappedPump;
+};
+
+/**
+ * LLEventLogProxyFor<T> is a wrapper around any of the LLEventPump subclasses.
+ * Instantiating an LLEventLogProxy<T> instantiates an internal T. Otherwise
+ * it behaves like LLEventLogProxy.
+ */
+template <class T>
+class LLEventLogProxyFor: private LLEventPumpHolder<T>, public LLEventLogProxy
+{
+ // We derive privately from LLEventPumpHolder because it's an
+ // implementation detail of LLEventLogProxyFor. The only reason it's a
+ // base class at all is to guarantee that it's constructed first so we can
+ // pass it to our LLEventLogProxy base class constructor.
+ typedef LLEventPumpHolder<T> holder;
+ typedef LLEventLogProxy super;
+
+public:
+ LLEventLogProxyFor(const std::string& name, bool tweak=false):
+ // our wrapped LLEventPump subclass instance gets a name suffix
+ // because that's not the LLEventPump we want consumers to obtain when
+ // they ask LLEventPumps for this name
+ holder(name + "-", tweak),
+ // it's our LLEventLogProxy that gets the passed name
+ super(holder::mWrappedPump, name, tweak)
+ {}
+};
+
#endif /* ! defined(LL_LLEVENTFILTER_H) */