summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2024-03-24 02:16:55 +0900
committerNat Goodspeed <nat@lindenlab.com>2024-03-24 02:16:55 +0900
commit93b30f960ea327fe3c36deed72a8075ce0d13f19 (patch)
tree10894a7372bfed0ae94f7217e03c8d03050a042e /indra/llcommon
parent2dc003779443db99f46b3db6d17a1954f7b141dd (diff)
Introduce LLStreamListener: bundle LLEventStream+LLTempBoundListener.
This is a very common pattern, especially in test code, but elsewhere in the viewer too. Use it in llluamanager_test.cpp.
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/llevents.h43
1 files changed, 43 insertions, 0 deletions
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
index 1f35a6de18..ebc893d1e6 100644
--- a/indra/llcommon/llevents.h
+++ b/indra/llcommon/llevents.h
@@ -151,6 +151,8 @@ typedef boost::signals2::signal<bool(const LLSD&), LLStopWhenHandled, float> LL
/// Methods that forward listeners (e.g. constructed with
/// <tt>boost::bind()</tt>) should accept (const LLEventListener&)
typedef LLStandardSignal::slot_type LLEventListener;
+/// Accept a void listener too
+typedef std::function<void(const LLSD&)> LLVoidListener;
/// Result of registering a listener, supports <tt>connected()</tt>,
/// <tt>disconnect()</tt> and <tt>blocked()</tt>
typedef boost::signals2::connection LLBoundListener;
@@ -158,6 +160,23 @@ typedef boost::signals2::connection LLBoundListener;
/// referenced listener when the LLTempBoundListener instance is destroyed.
typedef boost::signals2::scoped_connection LLTempBoundListener;
+/// Accepting (const LLListener&) allows either LLEventListener or LLVoidListener
+/// TODO: but compiler considers the constructor call ambiguous??
+class LLListener
+{
+public:
+ LLListener(const LLEventListener& listener):
+ mListener(listener)
+ {}
+ LLListener(const LLVoidListener& listener):
+ mListener([listener](const LLSD& data){ listener(data); return false; })
+ {}
+ operator LLEventListener() const { return mListener; }
+
+private:
+ LLEventListener mListener;
+};
+
/**
* A common idiom for event-based code is to accept either a callable --
* directly called on completion -- or the string name of an LLEventPump on
@@ -688,6 +707,30 @@ private:
};
/*****************************************************************************
+* LLNamedListener
+*****************************************************************************/
+/**
+ * LLNamedListener bundles a concrete LLEventPump subclass with a specific
+ * listener function, with an LLTempBoundListener to ensure that it's
+ * disconnected before destruction.
+ */
+template <class PUMP=LLEventStream>
+class LL_COMMON_API LLNamedListener: PUMP
+{
+ using pump_t = PUMP;
+public:
+ template <typename LISTENER>
+ LLNamedListener(const std::string& name, LISTENER&& listener):
+ pump_t(name, false), // don't tweak the name
+ mConn(pump_t::listen("func", std::forward<LISTENER>(listener)))
+ {}
+
+private:
+ LLTempBoundListener mConn;
+};
+using LLStreamListener = LLNamedListener<>;
+
+/*****************************************************************************
* LLReqID
*****************************************************************************/
/**