From 2f866c9d9842a48e4f24b8bfb31de1aadcc6c00e Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Mon, 21 Oct 2019 13:10:58 -0400
Subject: [PATCH] DRTVWR-476: Add LLEventTimer::run_every(), run_at(),
 run_after().

Also add corresponding LLEventTimeout::post_every(), post_at(), post_after()
methods.
---
 indra/llcommon/lleventfilter.cpp | 22 ++++++++++
 indra/llcommon/lleventfilter.h   | 16 ++++++++
 indra/llcommon/lleventtimer.h    | 69 +++++++++++++++++++++++++++++++-
 3 files changed, 106 insertions(+), 1 deletion(-)

diff --git a/indra/llcommon/lleventfilter.cpp b/indra/llcommon/lleventfilter.cpp
index 06b3cb769e2..ae35fb9c8ec 100644
--- a/indra/llcommon/lleventfilter.cpp
+++ b/indra/llcommon/lleventfilter.cpp
@@ -38,6 +38,7 @@
 #include "llerror.h"                // LL_ERRS
 #include "llsdutil.h"               // llsd_matches()
 #include "stringize.h"
+#include "lldate.h"
 
 /*****************************************************************************
 *   LLEventFilter
@@ -183,6 +184,27 @@ bool LLEventTimeout::countdownElapsed() const
     return mTimer.hasExpired();
 }
 
+LLEventTimer* LLEventTimeout::post_every(F32 period, const std::string& pump, const LLSD& data)
+{
+    return LLEventTimer::run_every(
+        period,
+        [pump, data](){ LLEventPumps::instance().obtain(pump).post(data); });
+}
+
+LLEventTimer* LLEventTimeout::post_at(const LLDate& time, const std::string& pump, const LLSD& data)
+{
+    return LLEventTimer::run_at(
+        time,
+        [pump, data](){ LLEventPumps::instance().obtain(pump).post(data); });
+}
+
+LLEventTimer* LLEventTimeout::post_after(F32 interval, const std::string& pump, const LLSD& data)
+{
+    return LLEventTimer::run_after(
+        interval,
+        [pump, data](){ LLEventPumps::instance().obtain(pump).post(data); });
+}
+
 /*****************************************************************************
 *   LLEventBatch
 *****************************************************************************/
diff --git a/indra/llcommon/lleventfilter.h b/indra/llcommon/lleventfilter.h
index 79319353a73..f28d7e54aa9 100644
--- a/indra/llcommon/lleventfilter.h
+++ b/indra/llcommon/lleventfilter.h
@@ -33,8 +33,11 @@
 #include "stdtypes.h"
 #include "lltimer.h"
 #include "llsdutil.h"
+#include "lleventtimer.h"
 #include <boost/function.hpp>
 
+class LLDate;
+
 /**
  * Generic base class
  */
@@ -211,6 +214,19 @@ class LL_COMMON_API LLEventTimeout: public LLEventTimeoutBase
     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;
diff --git a/indra/llcommon/lleventtimer.h b/indra/llcommon/lleventtimer.h
index dc918121e12..dbbfe0c6e6c 100644
--- a/indra/llcommon/lleventtimer.h
+++ b/indra/llcommon/lleventtimer.h
@@ -40,16 +40,83 @@ class LL_COMMON_API LLEventTimer : public LLInstanceTracker<LLEventTimer>
 	LLEventTimer(F32 period);	// period is the amount of time between each call to tick() in seconds
 	LLEventTimer(const LLDate& time);
 	virtual ~LLEventTimer();
-	
+
 	//function to be called at the supplied frequency
 	// Normally return FALSE; TRUE will delete the timer after the function returns.
 	virtual BOOL tick() = 0;
 
 	static void updateClass();
 
+	/// Schedule recurring calls to generic callable every period seconds.
+	/// Returns a pointer; if you delete it, cancels the recurring calls.
+	template <typename CALLABLE>
+	static LLEventTimer* run_every(F32 period, const CALLABLE& callable);
+
+	/// Schedule a future call to generic callable. Returns a pointer.
+	/// CAUTION: The object referenced by that pointer WILL BE DELETED once
+	/// the callback has been called! LLEventTimer::getInstance(pointer) (NOT
+	/// pointer->getInstance(pointer)!) can be used to test whether the
+	/// pointer is still valid. If it is, deleting it will cancel the
+	/// callback.
+	template <typename CALLABLE>
+	static LLEventTimer* run_at(const LLDate& time, const CALLABLE& callable);
+
+	/// Like run_at(), but after a time delta rather than at a timestamp.
+	/// Same CAUTION.
+	template <typename CALLABLE>
+	static LLEventTimer* run_after(F32 interval, const CALLABLE& callable);
+
 protected:
 	LLTimer mEventTimer;
 	F32 mPeriod;
+
+private:
+	template <typename CALLABLE>
+	class Generic;
+};
+
+template <typename CALLABLE>
+class LLEventTimer::Generic: public LLEventTimer
+{
+public:
+    // making TIME generic allows engaging either LLEventTimer constructor
+    template <typename TIME>
+    Generic(const TIME& time, bool once, const CALLABLE& callable):
+        LLEventTimer(time),
+        mOnce(once),
+        mCallable(callable)
+    {}
+    BOOL tick() override
+    {
+        mCallable();
+        // true tells updateClass() to delete this instance
+        return mOnce;
+    }
+
+private:
+    bool mOnce;
+    CALLABLE mCallable;
 };
 
+template <typename CALLABLE>
+LLEventTimer* LLEventTimer::run_every(F32 period, const CALLABLE& callable)
+{
+    // return false to schedule recurring calls
+    return new Generic<CALLABLE>(period, false, callable);
+}
+
+template <typename CALLABLE>
+LLEventTimer* LLEventTimer::run_at(const LLDate& time, const CALLABLE& callable)
+{
+    // return true for one-shot callback
+    return new Generic<CALLABLE>(time, true, callable);
+}
+
+template <typename CALLABLE>
+LLEventTimer* LLEventTimer::run_after(F32 interval, const CALLABLE& callable)
+{
+    // one-shot callback after specified interval
+    return new Generic<CALLABLE>(interval, true, callable);
+}
+
 #endif //LL_EVENTTIMER_H
-- 
GitLab