summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llappearancemgr.cpp27
-rw-r--r--indra/newview/llappviewer.cpp1
-rw-r--r--indra/newview/llcallbacklist.cpp305
-rw-r--r--indra/newview/lldonotdisturbnotificationstorage.cpp4
-rw-r--r--indra/newview/lldonotdisturbnotificationstorage.h2
-rw-r--r--indra/newview/llfloaterlinkreplace.cpp10
-rw-r--r--indra/newview/llfloaterlinkreplace.h6
-rw-r--r--indra/newview/llfloaterpreference.cpp10
-rw-r--r--indra/newview/llfloaterregionrestarting.cpp4
-rw-r--r--indra/newview/llfloaterregionrestarting.h8
-rw-r--r--indra/newview/llfloateruipreview.cpp8
-rw-r--r--indra/newview/llimview.cpp6
-rw-r--r--indra/newview/llimview.h2
-rw-r--r--indra/newview/lllocalbitmaps.cpp13
-rw-r--r--indra/newview/lllocalbitmaps.h3
-rw-r--r--indra/newview/lllocalgltfmaterials.cpp13
-rw-r--r--indra/newview/lllocalgltfmaterials.h3
-rw-r--r--indra/newview/llmediadataclient.cpp8
-rw-r--r--indra/newview/llmediadataclient.h4
-rw-r--r--indra/newview/llpanelpeople.cpp29
-rw-r--r--indra/newview/llsetkeybinddialog.cpp16
-rw-r--r--indra/newview/llspeakers.cpp4
-rw-r--r--indra/newview/llspeakers.h2
-rw-r--r--indra/newview/lltoast.cpp36
-rw-r--r--indra/newview/lltoast.h8
-rw-r--r--indra/newview/llviewermessage.cpp8
-rw-r--r--indra/newview/llviewerparcelmediaautoplay.cpp4
-rw-r--r--indra/newview/llviewerparcelmediaautoplay.h2
-rw-r--r--indra/newview/scripts/lua/ErrorQueue.lua2
-rw-r--r--indra/newview/scripts/lua/Floater.lua32
-rw-r--r--indra/newview/scripts/lua/WaitQueue.lua2
-rw-r--r--indra/newview/scripts/lua/fiber.lua4
-rw-r--r--indra/newview/scripts/lua/leap.lua165
-rw-r--r--indra/newview/scripts/lua/printf.lua4
-rw-r--r--indra/newview/scripts/lua/test_timers.lua63
-rw-r--r--indra/newview/scripts/lua/timers.lua101
36 files changed, 410 insertions, 509 deletions
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 97e1c1e6ee..30f07a873b 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -118,26 +118,16 @@ public:
LLOutfitUnLockTimer(F32 period) : LLEventTimer(period)
{
// restart timer on BOF changed event
- LLOutfitObserver::instance().addBOFChangedCallback(boost::bind(
- &LLOutfitUnLockTimer::reset, this));
+ LLOutfitObserver::instance().addBOFChangedCallback([this]{ start(); });
stop();
}
- /*virtual*/
- BOOL tick()
+ bool tick() override
{
- if(mEventTimer.hasExpired())
- {
- LLAppearanceMgr::instance().setOutfitLocked(false);
- }
- return FALSE;
+ LLAppearanceMgr::instance().setOutfitLocked(false);
+ return false;
}
- void stop() { mEventTimer.stop(); }
- void start() { mEventTimer.start(); }
- void reset() { mEventTimer.reset(); }
- BOOL getStarted() { return mEventTimer.getStarted(); }
-
- LLTimer& getEventTimer() { return mEventTimer;}
+ bool getStarted() { return isRunning(); }
};
// support for secondlife:///app/appearance SLapps
@@ -332,7 +322,7 @@ public:
// virtual
// Will be deleted after returning true - only safe to do this if all callbacks have fired.
- BOOL tick()
+ bool tick() override
{
// mPendingRequests will be zero if all requests have been
// responded to. mWaitTimes.empty() will be true if we have
@@ -625,8 +615,8 @@ void LLBrokenLinkObserver::changed(U32 mask)
if (id == mUUID)
{
// Might not be processed yet and it is not a
- // good idea to update appearane here, postpone.
- doOnIdleOneTime([this]()
+ // good idea to update appearance here, postpone.
+ doOnIdleOneTime([this]
{
postProcess();
});
@@ -1712,7 +1702,6 @@ void LLAppearanceMgr::setOutfitLocked(bool locked)
mOutfitLocked = locked;
if (locked)
{
- mUnlockOutfitTimer->reset();
mUnlockOutfitTimer->start();
}
else
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 0709346acb..c9dc2b37f8 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -4614,7 +4614,6 @@ void LLAppViewer::idle()
LLFrameTimer::updateFrameTime();
LLFrameTimer::updateFrameCount();
- LLEventTimer::updateClass();
LLPerfStats::updateClass();
// LLApp::stepFrame() performs the above three calls plus mRunner.run().
diff --git a/indra/newview/llcallbacklist.cpp b/indra/newview/llcallbacklist.cpp
deleted file mode 100644
index 1674750351..0000000000
--- a/indra/newview/llcallbacklist.cpp
+++ /dev/null
@@ -1,305 +0,0 @@
-/**
- * @file llcallbacklist.cpp
- * @brief A simple list of callback functions to call.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llcallbacklist.h"
-#include "lleventtimer.h"
-
-// Library includes
-#include "llerror.h"
-
-
-//
-// Globals
-//
-LLCallbackList gIdleCallbacks;
-
-//
-// Member functions
-//
-
-LLCallbackList::LLCallbackList()
-{
- // nothing
-}
-
-LLCallbackList::~LLCallbackList()
-{
-}
-
-
-void LLCallbackList::addFunction( callback_t func, void *data)
-{
- if (!func)
- {
- LL_ERRS() << "LLCallbackList::addFunction - function is NULL" << LL_ENDL;
- return;
- }
-
- // only add one callback per func/data pair
- callback_pair_t t(func, data);
- callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t);
- if (iter == mCallbackList.end())
- {
- mCallbackList.push_back(t);
- }
-}
-
-
-BOOL LLCallbackList::containsFunction( callback_t func, void *data)
-{
- callback_pair_t t(func, data);
- callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t);
- if (iter != mCallbackList.end())
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
-
-BOOL LLCallbackList::deleteFunction( callback_t func, void *data)
-{
- callback_pair_t t(func, data);
- callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t);
- if (iter != mCallbackList.end())
- {
- mCallbackList.erase(iter);
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
-
-void LLCallbackList::deleteAllFunctions()
-{
- mCallbackList.clear();
-}
-
-
-void LLCallbackList::callFunctions()
-{
- for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end(); )
- {
- callback_list_t::iterator curiter = iter++;
- curiter->first(curiter->second);
- }
-}
-
-// Shim class to allow arbitrary boost::bind
-// expressions to be run as one-time idle callbacks.
-class OnIdleCallbackOneTime
-{
-public:
- OnIdleCallbackOneTime(nullary_func_t callable):
- mCallable(callable)
- {
- }
- static void onIdle(void *data)
- {
- gIdleCallbacks.deleteFunction(onIdle, data);
- OnIdleCallbackOneTime* self = reinterpret_cast<OnIdleCallbackOneTime*>(data);
- self->call();
- delete self;
- }
- void call()
- {
- mCallable();
- }
-private:
- nullary_func_t mCallable;
-};
-
-void doOnIdleOneTime(nullary_func_t callable)
-{
- OnIdleCallbackOneTime* cb_functor = new OnIdleCallbackOneTime(callable);
- gIdleCallbacks.addFunction(&OnIdleCallbackOneTime::onIdle,cb_functor);
-}
-
-// Shim class to allow generic boost functions to be run as
-// recurring idle callbacks. Callable should return true when done,
-// false to continue getting called.
-class OnIdleCallbackRepeating
-{
-public:
- OnIdleCallbackRepeating(bool_func_t callable):
- mCallable(callable)
- {
- }
- // Will keep getting called until the callable returns true.
- static void onIdle(void *data)
- {
- OnIdleCallbackRepeating* self = reinterpret_cast<OnIdleCallbackRepeating*>(data);
- bool done = self->call();
- if (done)
- {
- gIdleCallbacks.deleteFunction(onIdle, data);
- delete self;
- }
- }
- bool call()
- {
- return mCallable();
- }
-private:
- bool_func_t mCallable;
-};
-
-void doOnIdleRepeating(bool_func_t callable)
-{
- OnIdleCallbackRepeating* cb_functor = new OnIdleCallbackRepeating(callable);
- gIdleCallbacks.addFunction(&OnIdleCallbackRepeating::onIdle,cb_functor);
-}
-
-class NullaryFuncEventTimer: public LLEventTimer
-{
-public:
- NullaryFuncEventTimer(nullary_func_t callable, F32 seconds):
- LLEventTimer(seconds),
- mCallable(callable)
- {
- }
-
-private:
- BOOL tick()
- {
- mCallable();
- return TRUE;
- }
-
- nullary_func_t mCallable;
-};
-
-// Call a given callable once after specified interval.
-void doAfterInterval(nullary_func_t callable, F32 seconds)
-{
- new NullaryFuncEventTimer(callable, seconds);
-}
-
-class BoolFuncEventTimer: public LLEventTimer
-{
-public:
- BoolFuncEventTimer(bool_func_t callable, F32 seconds):
- LLEventTimer(seconds),
- mCallable(callable)
- {
- }
-private:
- BOOL tick()
- {
- return mCallable();
- }
-
- bool_func_t mCallable;
-};
-
-// Call a given callable every specified number of seconds, until it returns true.
-void doPeriodically(bool_func_t callable, F32 seconds)
-{
- new BoolFuncEventTimer(callable, seconds);
-}
-
-#ifdef _DEBUG
-
-void test1(void *data)
-{
- S32 *s32_data = (S32 *)data;
- LL_INFOS() << "testfunc1 " << *s32_data << LL_ENDL;
-}
-
-
-void test2(void *data)
-{
- S32 *s32_data = (S32 *)data;
- LL_INFOS() << "testfunc2 " << *s32_data << LL_ENDL;
-}
-
-
-void
-LLCallbackList::test()
-{
- S32 a = 1;
- S32 b = 2;
- LLCallbackList *list = new LLCallbackList;
-
- LL_INFOS() << "Testing LLCallbackList" << LL_ENDL;
-
- if (!list->deleteFunction(NULL))
- {
- LL_INFOS() << "passed 1" << LL_ENDL;
- }
- else
- {
- LL_INFOS() << "error, removed function from empty list" << LL_ENDL;
- }
-
- // LL_INFOS() << "This should crash" << LL_ENDL;
- // list->addFunction(NULL);
-
- list->addFunction(&test1, &a);
- list->addFunction(&test1, &a);
-
- LL_INFOS() << "Expect: test1 1, test1 1" << LL_ENDL;
- list->callFunctions();
-
- list->addFunction(&test1, &b);
- list->addFunction(&test2, &b);
-
- LL_INFOS() << "Expect: test1 1, test1 1, test1 2, test2 2" << LL_ENDL;
- list->callFunctions();
-
- if (list->deleteFunction(&test1, &b))
- {
- LL_INFOS() << "passed 3" << LL_ENDL;
- }
- else
- {
- LL_INFOS() << "error removing function" << LL_ENDL;
- }
-
- LL_INFOS() << "Expect: test1 1, test1 1, test2 2" << LL_ENDL;
- list->callFunctions();
-
- list->deleteAllFunctions();
-
- LL_INFOS() << "Expect nothing" << LL_ENDL;
- list->callFunctions();
-
- LL_INFOS() << "nothing :-)" << LL_ENDL;
-
- delete list;
-
- LL_INFOS() << "test complete" << LL_ENDL;
-}
-
-#endif // _DEBUG
diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp
index 18456d132f..b4ced668d0 100644
--- a/indra/newview/lldonotdisturbnotificationstorage.cpp
+++ b/indra/newview/lldonotdisturbnotificationstorage.cpp
@@ -55,7 +55,7 @@ LLDoNotDisturbNotificationStorageTimer::~LLDoNotDisturbNotificationStorageTimer(
}
-BOOL LLDoNotDisturbNotificationStorageTimer::tick()
+bool LLDoNotDisturbNotificationStorageTimer::tick()
{
LLDoNotDisturbNotificationStorage * doNotDisturbNotificationStorage = LLDoNotDisturbNotificationStorage::getInstance();
@@ -64,7 +64,7 @@ BOOL LLDoNotDisturbNotificationStorageTimer::tick()
{
doNotDisturbNotificationStorage->saveNotifications();
}
- return FALSE;
+ return false;
}
LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage()
diff --git a/indra/newview/lldonotdisturbnotificationstorage.h b/indra/newview/lldonotdisturbnotificationstorage.h
index 1432d37de6..0dc2515e02 100644
--- a/indra/newview/lldonotdisturbnotificationstorage.h
+++ b/indra/newview/lldonotdisturbnotificationstorage.h
@@ -42,7 +42,7 @@ public:
~LLDoNotDisturbNotificationStorageTimer();
public:
- BOOL tick();
+ bool tick() override;
};
class LLDoNotDisturbNotificationStorage : public LLParamSingleton<LLDoNotDisturbNotificationStorage>, public LLNotificationStorage
diff --git a/indra/newview/llfloaterlinkreplace.cpp b/indra/newview/llfloaterlinkreplace.cpp
index bd1d8ddae8..956ab0d7bc 100644
--- a/indra/newview/llfloaterlinkreplace.cpp
+++ b/indra/newview/llfloaterlinkreplace.cpp
@@ -45,7 +45,7 @@ LLFloaterLinkReplace::LLFloaterLinkReplace(const LLSD& key)
mTargetUUID(LLUUID::null),
mBatchSize(gSavedSettings.getU32("LinkReplaceBatchSize"))
{
- mEventTimer.stop();
+ stop();
}
LLFloaterLinkReplace::~LLFloaterLinkReplace()
@@ -202,7 +202,7 @@ void LLFloaterLinkReplace::onStartClickedResponse(const LLSD& notification, cons
mStartBtn->setEnabled(FALSE);
mRefreshBtn->setEnabled(FALSE);
- mEventTimer.start();
+ start();
tick();
}
else
@@ -298,7 +298,7 @@ void LLFloaterLinkReplace::decreaseOpenItemCount()
mStatusText->setText(getString("ReplaceFinished"));
mStartBtn->setEnabled(TRUE);
mRefreshBtn->setEnabled(TRUE);
- mEventTimer.stop();
+ stop();
LL_INFOS() << "Inventory link replace finished." << LL_ENDL;
}
else
@@ -310,7 +310,7 @@ void LLFloaterLinkReplace::decreaseOpenItemCount()
}
}
-BOOL LLFloaterLinkReplace::tick()
+bool LLFloaterLinkReplace::tick()
{
LL_DEBUGS() << "Calling tick - remaining items = " << mRemainingInventoryItems.size() << LL_ENDL;
@@ -320,7 +320,7 @@ BOOL LLFloaterLinkReplace::tick()
{
if (!mRemainingInventoryItems.size())
{
- mEventTimer.stop();
+ stop();
break;
}
diff --git a/indra/newview/llfloaterlinkreplace.h b/indra/newview/llfloaterlinkreplace.h
index 0eee0d6935..e2fff20735 100644
--- a/indra/newview/llfloaterlinkreplace.h
+++ b/indra/newview/llfloaterlinkreplace.h
@@ -86,10 +86,10 @@ public:
LLFloaterLinkReplace(const LLSD& key);
virtual ~LLFloaterLinkReplace();
- BOOL postBuild();
- virtual void onOpen(const LLSD& key);
+ BOOL postBuild() override;
+ void onOpen(const LLSD& key) override;
- virtual BOOL tick();
+ bool tick() override;
private:
void checkEnableStart();
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index d731f1c592..cf7b96287c 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -1944,7 +1944,7 @@ public:
:LLEventTimer(period),
mCallback(cb)
{
- mEventTimer.stop();
+ stop();
}
virtual ~Updater(){}
@@ -1952,17 +1952,17 @@ public:
void update(const LLSD& new_value)
{
mNewValue = new_value;
- mEventTimer.start();
+ start();
}
protected:
- BOOL tick()
+ bool tick() override
{
mCallback(mNewValue);
- mEventTimer.stop();
+ stop();
- return FALSE;
+ return false;
}
private:
diff --git a/indra/newview/llfloaterregionrestarting.cpp b/indra/newview/llfloaterregionrestarting.cpp
index 1df2825fe0..d37a2912a0 100644
--- a/indra/newview/llfloaterregionrestarting.cpp
+++ b/indra/newview/llfloaterregionrestarting.cpp
@@ -74,11 +74,11 @@ void LLFloaterRegionRestarting::regionChange()
close();
}
-BOOL LLFloaterRegionRestarting::tick()
+bool LLFloaterRegionRestarting::tick()
{
refresh();
- return FALSE;
+ return false;
}
void LLFloaterRegionRestarting::refresh()
diff --git a/indra/newview/llfloaterregionrestarting.h b/indra/newview/llfloaterregionrestarting.h
index ab080073e7..52f067fa94 100644
--- a/indra/newview/llfloaterregionrestarting.h
+++ b/indra/newview/llfloaterregionrestarting.h
@@ -42,10 +42,10 @@ public:
private:
LLFloaterRegionRestarting(const LLSD& key);
virtual ~LLFloaterRegionRestarting();
- virtual BOOL postBuild();
- virtual BOOL tick();
- virtual void refresh();
- virtual void draw();
+ BOOL postBuild() override;
+ bool tick() override;
+ void refresh() override;
+ void draw() override;
virtual void regionChange();
std::string mName;
diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp
index 4db76c7971..4e35290a3b 100644
--- a/indra/newview/llfloateruipreview.cpp
+++ b/indra/newview/llfloateruipreview.cpp
@@ -254,7 +254,7 @@ class LLFadeEventTimer : public LLEventTimer
{
public:
LLFadeEventTimer(F32 refresh, LLGUIPreviewLiveFile* parent);
- BOOL tick();
+ bool tick() override;
LLGUIPreviewLiveFile* mParent;
private:
BOOL mFadingOut; // fades in then out; this is toggled in between
@@ -355,7 +355,7 @@ LLFadeEventTimer::LLFadeEventTimer(F32 refresh, LLGUIPreviewLiveFile* parent)
}
// Single tick of fade event timer: increment the color
-BOOL LLFadeEventTimer::tick()
+bool LLFadeEventTimer::tick()
{
float diff = 0.04f;
if(TRUE == mFadingOut) // set fade for in/out color direction
@@ -365,7 +365,7 @@ BOOL LLFadeEventTimer::tick()
if(NULL == mParent) // no more need to tick, so suicide
{
- return TRUE;
+ return true;
}
// Set up colors
@@ -388,7 +388,7 @@ BOOL LLFadeEventTimer::tick()
mFadingOut = FALSE;
}
- return FALSE;
+ return false;
}
// Constructor
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 187dbdd3a2..0cd6fc0340 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -99,16 +99,16 @@ const LLUUID LLOutgoingCallDialog::OCD_KEY = LLUUID("7CF78E11-0CFE-498D-ADB9-141
LLIMMgr* gIMMgr = NULL;
-BOOL LLSessionTimeoutTimer::tick()
+bool LLSessionTimeoutTimer::tick()
{
- if (mSessionId.isNull()) return TRUE;
+ if (mSessionId.isNull()) return true;
LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId);
if (session && !session->mSessionInitialized)
{
gIMMgr->showSessionStartError("session_initialization_timed_out_error", mSessionId);
}
- return TRUE;
+ return true;
}
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 8d1bc1c76a..a8c1f28ad5 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -51,7 +51,7 @@ class LLSessionTimeoutTimer : public LLEventTimer
public:
LLSessionTimeoutTimer(const LLUUID& session_id, F32 period) : LLEventTimer(period), mSessionId(session_id) {}
virtual ~LLSessionTimeoutTimer() {};
- /* virtual */ BOOL tick();
+ bool tick() override;
private:
LLUUID mSessionId;
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index 5b7243ece2..a2a6210572 100644
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -996,23 +996,18 @@ LLLocalBitmapTimer::~LLLocalBitmapTimer()
void LLLocalBitmapTimer::startTimer()
{
- mEventTimer.start();
+ start();
}
void LLLocalBitmapTimer::stopTimer()
{
- mEventTimer.stop();
+ stop();
}
-bool LLLocalBitmapTimer::isRunning()
-{
- return mEventTimer.getStarted();
-}
-
-BOOL LLLocalBitmapTimer::tick()
+bool LLLocalBitmapTimer::tick()
{
LLLocalBitmapMgr::getInstance()->doUpdates();
- return FALSE;
+ return false;
}
/*=======================================*/
diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h
index 5dbc514f56..84811ee14a 100644
--- a/indra/newview/lllocalbitmaps.h
+++ b/indra/newview/lllocalbitmaps.h
@@ -120,8 +120,7 @@ class LLLocalBitmapTimer : public LLEventTimer
public:
void startTimer();
void stopTimer();
- bool isRunning();
- BOOL tick();
+ bool tick() override;
};
diff --git a/indra/newview/lllocalgltfmaterials.cpp b/indra/newview/lllocalgltfmaterials.cpp
index 58f06d7748..8019be6f42 100644
--- a/indra/newview/lllocalgltfmaterials.cpp
+++ b/indra/newview/lllocalgltfmaterials.cpp
@@ -288,24 +288,19 @@ LLLocalGLTFMaterialTimer::~LLLocalGLTFMaterialTimer()
void LLLocalGLTFMaterialTimer::startTimer()
{
- mEventTimer.start();
+ start();
}
void LLLocalGLTFMaterialTimer::stopTimer()
{
- mEventTimer.stop();
+ stop();
}
-bool LLLocalGLTFMaterialTimer::isRunning()
-{
- return mEventTimer.getStarted();
-}
-
-BOOL LLLocalGLTFMaterialTimer::tick()
+bool LLLocalGLTFMaterialTimer::tick()
{
// todo: do on idle? No point in timer
LLLocalGLTFMaterialMgr::getInstance()->doUpdates();
- return FALSE;
+ return false;
}
/*=======================================*/
diff --git a/indra/newview/lllocalgltfmaterials.h b/indra/newview/lllocalgltfmaterials.h
index a85bbf33ce..9c2d1bb287 100644
--- a/indra/newview/lllocalgltfmaterials.h
+++ b/indra/newview/lllocalgltfmaterials.h
@@ -89,8 +89,7 @@ public:
public:
void startTimer();
void stopTimer();
- bool isRunning();
- BOOL tick();
+ bool tick() override;
};
class LLLocalGLTFMaterialMgr : public LLSingleton<LLLocalGLTFMaterialMgr>
diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp
index 52898d1b86..828c0a0747 100644
--- a/indra/newview/llmediadataclient.cpp
+++ b/indra/newview/llmediadataclient.cpp
@@ -418,9 +418,9 @@ LLMediaDataClient::QueueTimer::QueueTimer(F32 time, LLMediaDataClient *mdc)
}
// virtual
-BOOL LLMediaDataClient::QueueTimer::tick()
+bool LLMediaDataClient::QueueTimer::tick()
{
- BOOL result = TRUE;
+ bool result = TRUE;
if (!mMDC.isNull())
{
@@ -451,7 +451,7 @@ LLMediaDataClient::RetryTimer::RetryTimer(F32 time, Request::ptr_t request)
}
// virtual
-BOOL LLMediaDataClient::RetryTimer::tick()
+bool LLMediaDataClient::RetryTimer::tick()
{
mRequest->stopTracking();
@@ -469,7 +469,7 @@ BOOL LLMediaDataClient::RetryTimer::tick()
mRequest.reset();
// Don't fire again
- return TRUE;
+ return true;
}
diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h
index ae5e5cd5d4..a5f20e51db 100644
--- a/indra/newview/llmediadataclient.h
+++ b/indra/newview/llmediadataclient.h
@@ -219,7 +219,7 @@ protected:
{
public:
RetryTimer(F32 time, Request::ptr_t);
- virtual BOOL tick();
+ virtual bool tick() override;
private:
// back-pointer
Request::ptr_t mRequest;
@@ -286,7 +286,7 @@ private:
{
public:
QueueTimer(F32 time, LLMediaDataClient *mdc);
- virtual BOOL tick();
+ bool tick() override;
private:
// back-pointer
LLPointer<LLMediaDataClient> mMDC;
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 44e860837e..163fb5ffd4 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -310,12 +310,12 @@ public:
: LLEventTimer(period),
LLPanelPeople::Updater(cb)
{
- mEventTimer.stop();
+ stop();
}
- virtual BOOL tick() // from LLEventTimer
+ bool tick() override // from LLEventTimer
{
- return FALSE;
+ return false;
}
};
@@ -353,13 +353,13 @@ public:
LLAvatarTracker::instance().removeObserver(this);
}
- /*virtual*/ void changed(U32 mask)
+ void changed(U32 mask) override
{
if (mIsActive)
{
// events can arrive quickly in bulk - we need not process EVERY one of them -
// so we wait a short while to let others pile-in, and process them in aggregate.
- mEventTimer.start();
+ start();
}
// save-up all the mask-bits which have come-in
@@ -367,7 +367,7 @@ public:
}
- /*virtual*/ BOOL tick()
+ bool tick() override
{
if (!mIsActive) return FALSE;
@@ -377,14 +377,13 @@ public:
}
// Stop updates.
- mEventTimer.stop();
+ stop();
mMask = 0;
- return FALSE;
+ return false;
}
- // virtual
- void setActive(bool active)
+ void setActive(bool active) override
{
mIsActive = active;
if (active)
@@ -493,25 +492,25 @@ public:
setActive(false);
}
- /*virtual*/ void setActive(bool val)
+ void setActive(bool val) override
{
if (val)
{
// update immediately and start regular updates
update();
- mEventTimer.start();
+ start();
}
else
{
// stop regular updates
- mEventTimer.stop();
+ stop();
}
}
- /*virtual*/ BOOL tick()
+ bool tick() override
{
update();
- return FALSE;
+ return false;
}
private:
};
diff --git a/indra/newview/llsetkeybinddialog.cpp b/indra/newview/llsetkeybinddialog.cpp
index dbab7e53b6..88405dc7e0 100644
--- a/indra/newview/llsetkeybinddialog.cpp
+++ b/indra/newview/llsetkeybinddialog.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llsetkeybinddialog.cpp
* @brief LLSetKeyBindDialog class implementation.
*
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2019, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -46,14 +46,12 @@ public:
:LLEventTimer(period),
mMask(mask),
mCallback(cb)
- {
- mEventTimer.start();
- }
+ {}
virtual ~Updater(){}
protected:
- BOOL tick()
+ bool tick() override
{
mCallback(mMask);
// Deletes itseft after execution
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index 2d8163d9e1..6799104f9a 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -181,13 +181,13 @@ LLSpeakerActionTimer::LLSpeakerActionTimer(action_callback_t action_cb, F32 acti
{
}
-BOOL LLSpeakerActionTimer::tick()
+bool LLSpeakerActionTimer::tick()
{
if (mActionCallback)
{
return (BOOL)mActionCallback(mSpeakerId);
}
- return TRUE;
+ return true;
}
void LLSpeakerActionTimer::unset()
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
index eb86fadea1..234de42953 100644
--- a/indra/newview/llspeakers.h
+++ b/indra/newview/llspeakers.h
@@ -159,7 +159,7 @@ public:
*
* If action callback is not specified returns true. Instance will be deleted by LLEventTimer::updateClass().
*/
- virtual BOOL tick();
+ bool tick() override;
/**
* Clears the callback.
diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp
index 2e00b2c382..2041d86fc6 100644
--- a/indra/newview/lltoast.cpp
+++ b/indra/newview/lltoast.cpp
@@ -43,34 +43,21 @@ LLToastLifeTimer::LLToastLifeTimer(LLToast* toast, F32 period)
{
}
-/*virtual*/
-BOOL LLToastLifeTimer::tick()
+bool LLToastLifeTimer::tick()
{
- if (mEventTimer.hasExpired())
- {
- mToast->expire();
- }
- return FALSE;
-}
-
-void LLToastLifeTimer::stop()
-{
- mEventTimer.stop();
-}
-
-void LLToastLifeTimer::start()
-{
- mEventTimer.start();
+ mToast->expire();
+ return false;
}
void LLToastLifeTimer::restart()
{
- mEventTimer.reset();
+ // start() discards any previously-running mTimer
+ start();
}
-BOOL LLToastLifeTimer::getStarted()
+bool LLToastLifeTimer::getStarted()
{
- return mEventTimer.getStarted();
+ return isRunning();
}
void LLToastLifeTimer::setPeriod(F32 period)
@@ -78,13 +65,6 @@ void LLToastLifeTimer::setPeriod(F32 period)
mPeriod = period;
}
-F32 LLToastLifeTimer::getRemainingTimeF32()
-{
- F32 et = mEventTimer.getElapsedTimeF32();
- if (!getStarted() || et > mPeriod) return 0.0f;
- return mPeriod - et;
-}
-
//--------------------------------------------------------------------------
LLToast::Params::Params()
: can_fade("can_fade", true),
@@ -337,7 +317,7 @@ void LLToast::setFading(bool transparent)
F32 LLToast::getTimeLeftToLive()
{
- F32 time_to_live = mTimer->getRemainingTimeF32();
+ F32 time_to_live = mTimer->getRemaining();
if (!mIsFading)
{
diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h
index a0003dfa70..bb5bd981e2 100644
--- a/indra/newview/lltoast.h
+++ b/indra/newview/lltoast.h
@@ -53,15 +53,11 @@ public:
LLToastLifeTimer(LLToast* toast, F32 period);
/*virtual*/
- BOOL tick();
- void stop();
- void start();
+ bool tick() override;
void restart();
- BOOL getStarted();
+ bool getStarted();
void setPeriod(F32 period);
- F32 getRemainingTimeF32();
- LLTimer& getEventTimer() { return mEventTimer;}
private :
LLToast* mToast;
};
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index d1c773171b..01d4695eda 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -2894,7 +2894,7 @@ public:
virtual ~LLPostTeleportNotifiers();
//function to be called at the supplied frequency
- virtual BOOL tick();
+ bool tick() override;
};
LLPostTeleportNotifiers::LLPostTeleportNotifiers() : LLEventTimer( 2.0 )
@@ -2905,9 +2905,9 @@ LLPostTeleportNotifiers::~LLPostTeleportNotifiers()
{
}
-BOOL LLPostTeleportNotifiers::tick()
+bool LLPostTeleportNotifiers::tick()
{
- BOOL all_done = FALSE;
+ bool all_done = false;
if ( gAgent.getTeleportState() == LLAgent::TELEPORT_NONE )
{
// get callingcards and landmarks available to the user arriving.
@@ -2931,7 +2931,7 @@ BOOL LLPostTeleportNotifiers::tick()
gInventory.addObserver(fetcher);
}
}
- all_done = TRUE;
+ all_done = true;
}
return all_done;
diff --git a/indra/newview/llviewerparcelmediaautoplay.cpp b/indra/newview/llviewerparcelmediaautoplay.cpp
index 6e0db94985..d9575e0b2b 100644
--- a/indra/newview/llviewerparcelmediaautoplay.cpp
+++ b/indra/newview/llviewerparcelmediaautoplay.cpp
@@ -60,7 +60,7 @@ void LLViewerParcelMediaAutoPlay::playStarted()
LLSingleton<LLViewerParcelMediaAutoPlay>::getInstance()->mPlayed = TRUE;
}
-BOOL LLViewerParcelMediaAutoPlay::tick()
+bool LLViewerParcelMediaAutoPlay::tick()
{
LLParcel *this_parcel = NULL;
LLViewerRegion *this_region = NULL;
@@ -156,7 +156,7 @@ BOOL LLViewerParcelMediaAutoPlay::tick()
}
- return FALSE; // continue ticking forever please.
+ return false; // continue ticking forever please.
}
//static
diff --git a/indra/newview/llviewerparcelmediaautoplay.h b/indra/newview/llviewerparcelmediaautoplay.h
index ee228e8425..506fb38901 100644
--- a/indra/newview/llviewerparcelmediaautoplay.h
+++ b/indra/newview/llviewerparcelmediaautoplay.h
@@ -35,7 +35,7 @@ class LLViewerParcelMediaAutoPlay : LLEventTimer, public LLSingleton<LLViewerPar
{
LLSINGLETON(LLViewerParcelMediaAutoPlay);
public:
- virtual BOOL tick() override;
+ bool tick() override;
static void playStarted();
private:
diff --git a/indra/newview/scripts/lua/ErrorQueue.lua b/indra/newview/scripts/lua/ErrorQueue.lua
index 6ed1c10d5c..13e4e92941 100644
--- a/indra/newview/scripts/lua/ErrorQueue.lua
+++ b/indra/newview/scripts/lua/ErrorQueue.lua
@@ -3,8 +3,8 @@
-- raise that error.
local WaitQueue = require('WaitQueue')
--- local dbg = require('printf')
local function dbg(...) end
+-- local dbg = require('printf')
local ErrorQueue = WaitQueue:new()
diff --git a/indra/newview/scripts/lua/Floater.lua b/indra/newview/scripts/lua/Floater.lua
index 76efd47c43..75696533e4 100644
--- a/indra/newview/scripts/lua/Floater.lua
+++ b/indra/newview/scripts/lua/Floater.lua
@@ -46,10 +46,18 @@ function Floater:new(path, extra)
end
function Floater:show()
- local event = leap.request('LLFloaterReg', self._command)
+ -- leap.eventstream() returns the first response, and launches a
+ -- background fiber to call the passed callback with all subsequent
+ -- responses.
+ local event = leap.eventstream(
+ 'LLFloaterReg',
+ self._command,
+ -- handleEvents() returns false when done.
+ -- eventstream() expects a true return when done.
+ function(event) return not self:handleEvents(event) end)
self._pump = event.command_name
- -- we use the returned reqid to claim subsequent unsolicited events
- local reqid = event.reqid
+ -- we might need the returned reqid to cancel the eventstream() fiber
+ self.reqid = event.reqid
-- The response to 'showLuaFloater' *is* the 'post_build' event. Check if
-- subclass has a post_build() method. Honor the convention that if
@@ -57,22 +65,6 @@ function Floater:show()
if not self:handleEvents(event) then
return
end
-
- local waitfor = leap.WaitFor:new(-1, self.name)
- function waitfor:filter(pump, data)
- if data.reqid == reqid then
- return data
- end
- end
-
- fiber.launch(
- self.name,
- function ()
- event = waitfor:wait()
- while event and self:handleEvents(event) do
- event = waitfor:wait()
- end
- end)
end
function Floater:post(action)
@@ -125,7 +117,7 @@ function Floater:handleEvents(event_data)
-- We check for event() method before recognizing floater_close in case
-- the consumer needs to react specially to closing the floater. Now that
-- we've checked, recognize it ourselves. Returning false terminates the
- -- anonymous fiber function launched by show().
+ -- anonymous fiber function launched by leap.eventstream().
if event == _event('floater_close') then
LL.print_warning(self.name .. ' closed')
return false
diff --git a/indra/newview/scripts/lua/WaitQueue.lua b/indra/newview/scripts/lua/WaitQueue.lua
index ad4fdecf43..6bcb9d62c2 100644
--- a/indra/newview/scripts/lua/WaitQueue.lua
+++ b/indra/newview/scripts/lua/WaitQueue.lua
@@ -5,8 +5,8 @@
local fiber = require('fiber')
local Queue = require('Queue')
--- local dbg = require('printf')
local function dbg(...) end
+-- local dbg = require('printf')
local WaitQueue = Queue:new()
diff --git a/indra/newview/scripts/lua/fiber.lua b/indra/newview/scripts/lua/fiber.lua
index 9057e6c890..cae27b936b 100644
--- a/indra/newview/scripts/lua/fiber.lua
+++ b/indra/newview/scripts/lua/fiber.lua
@@ -17,8 +17,8 @@
-- or with an error).
local printf = require 'printf'
--- local dbg = printf
local function dbg(...) end
+-- local dbg = printf
local coro = require 'coro'
local fiber = {}
@@ -303,6 +303,8 @@ function fiber.yield()
end
-- We're ready! Just return to caller. In this situation we don't care
-- whether there are other ready fibers.
+ dbg('fiber.yield() returning to %s (%sothers are ready)',
+ fiber.get_name(), ((not others) and "no " or ""))
end
-- Run fibers until all but main have terminated: return nil.
diff --git a/indra/newview/scripts/lua/leap.lua b/indra/newview/scripts/lua/leap.lua
index ade91789f0..8caae24e94 100644
--- a/indra/newview/scripts/lua/leap.lua
+++ b/indra/newview/scripts/lua/leap.lua
@@ -40,6 +40,7 @@
local fiber = require('fiber')
local ErrorQueue = require('ErrorQueue')
+local inspect = require('inspect')
local function dbg(...) end
-- local dbg = require('printf')
@@ -74,7 +75,7 @@ local reply, command = LL.get_event_pumps()
-- pending is NOT a weak table because the caller of request() or generate()
-- never sees the WaitForReqid object. pending holds the only reference, so
-- it should NOT be garbage-collected.
-pending = {}
+local pending = {}
-- Our consumer will instantiate some number of WaitFor subclass objects.
-- As these are traversed in descending priority order, we must keep
-- them in a list.
@@ -82,7 +83,7 @@ pending = {}
-- to it. Once the consuming script drops the reference, allow Lua to
-- garbage-collect the WaitFor despite its entry in waitfors.
local weak_values = {__mode='v'}
-waitfors = setmetatable({}, weak_values)
+local waitfors = setmetatable({}, weak_values)
-- It has been suggested that we should use UUIDs as ["reqid"] values,
-- since UUIDs are guaranteed unique. However, as the "namespace" for
-- ["reqid"] values is our very own reply pump, we can get away with
@@ -131,7 +132,7 @@ local function requestSetup(pump, data)
local waitfor = leap.WaitForReqid:new(reqid)
pending[reqid] = waitfor
-- Pass reqid to send() to stamp it into (a copy of) the request data.
- dbg('requestSetup(%s, %s)', pump, data)
+ dbg('requestSetup(%s, %s) storing %s', pump, data, waitfor.name)
leap.send(pump, data, reqid)
return reqid, waitfor
end
@@ -161,50 +162,137 @@ function leap.request(pump, data)
dbg('leap.request(%s, %s) got %s: %s', pump, data, ok, response)
-- kill off temporary WaitForReqid object, even if error
pending[reqid] = nil
- if ok then
- return response
- else
+ if not ok then
error(response)
+ elseif response.error then
+ error(response.error)
+ else
+ return response
end
end
-- Send the specified request LLSD, expecting an arbitrary number of replies.
--- Each one is yielded on receipt. If you omit checklast, this is an infinite
--- generator; it's up to the caller to recognize when the last reply has been
--- received, and stop resuming for more.
---
--- If you pass checklast=<callable accepting(event)>, each response event is
--- passed to that callable (after the yield). When the callable returns
--- True, the generator terminates in the usual way.
+-- Each one is returned on request.
+--
+-- Usage:
+-- sequence = leap.generate(pump, data)
+-- repeat
+-- response = sequence.next()
+-- until last(response)
+-- (last() means whatever test the caller wants to perform on response)
+-- sequence.done()
--
-- See request() remarks about ["reqid"].
+--
+-- Note: this seems like a prime use case for Lua coroutines. But in a script
+-- using fibers.lua, a "wild" coroutine confuses the fiber scheduler. If
+-- generate() were itself a coroutine, it would call WaitForReqid:wait(),
+-- which would yield -- thereby resuming generate() WITHOUT waiting.
function leap.generate(pump, data, checklast)
-- Invent a new, unique reqid. Arrange to handle incoming events
-- bearing that reqid. Stamp the outbound request with that reqid, and
-- send it.
local reqid, waitfor = requestSetup(pump, data)
- local ok, response, resumed_with
- repeat
- ok, response = pcall(waitfor.wait, waitfor)
- if not ok then
- break
+ return {
+ next = function()
+ dbg('leap.generate(%s).next() about to wait on %s', reqid, tostring(waitfor))
+ local ok, response = pcall(waitfor.wait, waitfor)
+ dbg('leap.generate(%s).next() got %s: %s', reqid, ok, response)
+ if not ok then
+ error(response)
+ elseif response.error then
+ error(response.error)
+ else
+ return response
+ end
+ end,
+ done = function()
+ -- cleanup consists of removing our WaitForReqid from pending
+ pending[reqid] = nil
end
- -- can resume(false) to terminate generate() and clean up
- resumed_with = coroutine.yield(response)
- until (checklast and checklast(response)) or (resumed_with == false)
- -- If we break the above loop, whether or not due to error, clean up.
- pending[reqid] = nil
+ }
+end
+
+-- Send the specified request LLSD, expecting an immediate reply followed by
+-- an arbitrary number of subsequent replies with the same reqid. Block the
+-- calling coroutine until the first (immediate) reply, but launch a separate
+-- fiber on which to call the passed callback with later replies.
+--
+-- Once the callback returns true, the background fiber terminates.
+function leap.eventstream(pump, data, callback)
+ local reqid, waitfor = requestSetup(pump, data)
+ local response = waitfor:wait()
+ if response.error then
+ -- clean up our WaitForReqid
+ waitfor:close()
+ error(response.error)
+ end
+ -- No error, so far so good:
+ -- call the callback with the first response just in case
+ dbg('leap.eventstream(%s): first callback', reqid)
+ local ok, done = pcall(callback, response)
+ dbg('leap.eventstream(%s) got %s, %s', reqid, ok, done)
if not ok then
- error(response)
+ -- clean up our WaitForReqid
+ waitfor:close()
+ error(done)
+ end
+ if done then
+ return response
+ end
+ -- callback didn't throw an error, and didn't say stop,
+ -- so set up to handle subsequent events
+ -- TODO: distinguish "daemon" fibers that can be terminated even if waiting
+ fiber.launch(
+ pump,
+ function ()
+ local ok, done
+ local nth = 1
+ repeat
+ event = waitfor:wait()
+ if not event then
+ -- wait() returns nil once the queue is closed (e.g. cancelreq())
+ ok, done = true, true
+ else
+ nth += 1
+ dbg('leap.eventstream(%s): callback %d', reqid, nth)
+ ok, done = pcall(callback, event)
+ dbg('leap.eventstream(%s) got %s, %s', reqid, ok, done)
+ end
+ -- not ok means callback threw an error (caught as 'done')
+ -- done means callback succeeded but wants to stop
+ until (not ok) or done
+ -- once we break this loop, clean up our WaitForReqid
+ waitfor:close()
+ if not ok then
+ -- can't reflect the error back to our caller
+ LL.print_warning(fiber.get_name() .. ': ' .. done)
+ end
+ end)
+ return response
+end
+
+-- we might want to clean up after leap.eventstream() even if the callback has
+-- not yet returned true
+function leap.cancelreq(reqid)
+ dbg('cancelreq(%s)', reqid)
+ local waitfor = pending[reqid]
+ if waitfor ~= nil then
+ -- close() removes the pending entry and also closes the queue,
+ -- breaking the background fiber's wait loop.
+ dbg('cancelreq(%s) canceling %s', reqid, waitfor.name)
+ waitfor:close()
end
end
local function cleanup(message)
- -- we're done: clean up all pending coroutines
- for i, waitfor in pairs(pending) do
+ -- We're done: clean up all pending coroutines.
+ -- Iterate over copies of the pending and waitfors tables, since the
+ -- close() operation modifies the real tables.
+ for i, waitfor in pairs(table.clone(pending)) do
waitfor:close()
end
- for i, waitfor in pairs(waitfors) do
+ for i, waitfor in pairs(table.clone(waitfors)) do
waitfor:close()
end
end
@@ -219,7 +307,8 @@ local function unsolicited(pump, data)
return
end
end
- LL.print_debug(string.format('unsolicited(%s, %s) discarding unclaimed event', pump, data))
+ LL.print_debug(string.format('unsolicited(%s, %s) discarding unclaimed event',
+ pump, inspect(data)))
end
-- Route incoming (pump, data) event to the appropriate waiting coroutine.
@@ -227,14 +316,17 @@ local function dispatch(pump, data)
local reqid = data['reqid']
-- if the response has no 'reqid', it's not from request() or generate()
if reqid == nil then
+-- dbg('dispatch() found no reqid; calling unsolicited(%s, %s)', pump, data)
return unsolicited(pump, data)
end
-- have reqid; do we have a WaitForReqid?
local waitfor = pending[reqid]
if waitfor == nil then
+-- dbg('dispatch() found no WaitForReqid(%s); calling unsolicited(%s, %s)', reqid, pump, data)
return unsolicited(pump, data)
end
-- found the right WaitForReqid object, let it handle the event
+-- dbg('dispatch() calling %s.handle(%s, %s)', waitfor.name, pump, data)
waitfor:handle(pump, data)
end
@@ -280,11 +372,9 @@ end
-- called by WaitFor.disable()
local function unregisterWaitFor(waitfor)
- for i, w in pairs(waitfors) do
- if w == waitfor then
- waitfors[i] = nil
- break
- end
+ local i = table.find(waitfors, waitfor)
+ if i ~= nil then
+ waitfors[i] = nil
end
end
@@ -413,6 +503,7 @@ end
-- called by cleanup() at end
function leap.WaitFor:close()
+ self:disable()
self._queue:close()
end
@@ -433,6 +524,8 @@ function leap.WaitForReqid:new(reqid)
setmetatable(obj, self)
self.__index = self
+ obj.reqid = reqid
+
return obj
end
@@ -443,4 +536,10 @@ function leap.WaitForReqid:filter(pump, data)
return data
end
+function leap.WaitForReqid:close()
+ -- remove this entry from pending table
+ pending[self.reqid] = nil
+ self._queue:close()
+end
+
return leap
diff --git a/indra/newview/scripts/lua/printf.lua b/indra/newview/scripts/lua/printf.lua
index 584cd4f391..e84b2024df 100644
--- a/indra/newview/scripts/lua/printf.lua
+++ b/indra/newview/scripts/lua/printf.lua
@@ -2,7 +2,7 @@
local inspect = require 'inspect'
-local function printf(...)
+local function printf(format, ...)
-- string.format() only handles numbers and strings.
-- Convert anything else to string using the inspect module.
local args = {}
@@ -13,7 +13,7 @@ local function printf(...)
table.insert(args, inspect(arg))
end
end
- print(string.format(table.unpack(args)))
+ print(string.format(format, table.unpack(args)))
end
return printf
diff --git a/indra/newview/scripts/lua/test_timers.lua b/indra/newview/scripts/lua/test_timers.lua
new file mode 100644
index 0000000000..ed0de070f7
--- /dev/null
+++ b/indra/newview/scripts/lua/test_timers.lua
@@ -0,0 +1,63 @@
+local timers = require 'timers'
+
+-- This t0 is constructed for 10 seconds, but its purpose is to exercise the
+-- query and cancel methods. It would print "t0 fired at..." if it fired, but
+-- it doesn't, so you don't see that message. Instead you see that isRunning()
+-- is true, that timeUntilCall() is (true, close to 10), that cancel() returns
+-- true. After that, isRunning() is false, timeUntilCall() returns (false, 0),
+-- and a second cancel() returns false.
+print('t0:new(10)')
+start = os.clock()
+t0 = timers.Timer:new(10, function() print('t0 fired at', os.clock() - start) end)
+print('t0:isRunning(): ', t0:isRunning())
+print('t0:timeUntilCall(): ', t0:timeUntilCall())
+print('t0:cancel(): ', t0:cancel())
+print('t0:isRunning(): ', t0:isRunning())
+print('t0:timeUntilCall(): ', t0:timeUntilCall())
+print('t0:cancel(): ', t0:cancel())
+
+-- t1 is supposed to fire after 5 seconds, but it doesn't wait, so you see the
+-- t2 messages immediately after.
+print('t1:new(5)')
+start = os.clock()
+t1 = timers.Timer:new(5, function() print('t1 fired at', os.clock() - start) end)
+
+-- t2 illustrates that instead of passing a callback to new(), you can
+-- override the timer instance's tick() method. But t2 doesn't wait either, so
+-- you see the Timer(5) message immediately.
+print('t2:new(2)')
+start = os.clock()
+t2 = timers.Timer:new(2)
+function t2:tick()
+ print('t2 fired at', os.clock() - start)
+end
+
+-- This anonymous timer blocks the calling fiber for 5 seconds. Other fibers
+-- are free to run during that time, so you see the t2 callback message and
+-- then the t1 callback message before the Timer(5) completion message.
+print('Timer(5) waiting')
+start = os.clock()
+timers.Timer:new(5, 'wait')
+print(string.format('Timer(5) waited %f seconds', os.clock() - start))
+
+-- This test demonstrates a repeating timer. It also shows that you can (but
+-- need not) use a coroutine as the timer's callback function: unlike Python,
+-- Lua doesn't disinguish between yield() and return. A coroutine wrapped with
+-- coroutine.wrap() looks to Lua just like any other function that you can
+-- call repeatedly and get a result each time. We use that to count the
+-- callback calls and stop after a certain number. Of course that could also
+-- be arranged in a plain function by incrementing a script-scope counter, but
+-- it's worth knowing that a coroutine timer callback can be used to manage
+-- more complex control flows.
+start = os.clock()
+timers.Timer:new(
+ 2,
+ coroutine.wrap(function()
+ for i = 1,5 do
+ print('repeat(2) timer fired at ', os.clock() - start)
+ coroutine.yield(nil) -- keep running
+ end
+ print('repeat(2) timer fired last at ', os.clock() - start)
+ return true -- stop
+ end),
+ true) -- iterate
diff --git a/indra/newview/scripts/lua/timers.lua b/indra/newview/scripts/lua/timers.lua
new file mode 100644
index 0000000000..e0d27a680d
--- /dev/null
+++ b/indra/newview/scripts/lua/timers.lua
@@ -0,0 +1,101 @@
+-- Access to the viewer's time-delay facilities
+
+local leap = require 'leap'
+
+local timers = {}
+
+local function dbg(...) end
+-- local dbg = require 'printf'
+
+timers.Timer = {}
+
+-- delay: time in seconds until callback
+-- callback: 'wait', or function to call when timer fires (self:tick if nil)
+-- iterate: if non-nil, call callback repeatedly until it returns non-nil
+-- (ignored if 'wait')
+function timers.Timer:new(delay, callback, iterate)
+ local obj = setmetatable({}, self)
+ self.__index = self
+
+ if callback == 'wait' then
+ dbg('scheduleAfter(%d):', delay)
+ sequence = leap.generate('Timers', {op='scheduleAfter', after=delay})
+ -- ignore the immediate return
+ dbg('scheduleAfter(%d) -> %s', delay,
+ sequence.next())
+ -- this call is where we wait for real
+ dbg('next():')
+ dbg('next() -> %s',
+ sequence.next())
+ sequence.done()
+ return
+ end
+
+ callback = callback or function() obj:tick() end
+
+ local first = true
+ if iterate then
+ obj.id = leap.eventstream(
+ 'Timers',
+ {op='scheduleEvery', every=delay},
+ function (event)
+ local reqid = event.reqid
+ if first then
+ first = false
+ dbg('timer(%s) first callback', reqid)
+ -- discard the first (immediate) response: don't call callback
+ return nil
+ else
+ dbg('timer(%s) nth callback', reqid)
+ return callback(event)
+ end
+ end
+ ).reqid
+ else
+ obj.id = leap.eventstream(
+ 'Timers',
+ {op='scheduleAfter', after=delay},
+ function (event)
+ -- Arrange to return nil the first time, true the second. This
+ -- callback is called immediately with the response to
+ -- 'scheduleAfter', and if we immediately returned true, we'd
+ -- be done, and the subsequent timer event would be discarded.
+ if first then
+ first = false
+ -- Caller doesn't expect an immediate callback.
+ return nil
+ else
+ callback(event)
+ -- Since caller doesn't want to iterate, the value
+ -- returned by the callback is irrelevant: just stop after
+ -- this one and only call.
+ return true
+ end
+ end
+ ).reqid
+ end
+
+ return obj
+end
+
+function timers.Timer:tick()
+ error('Pass a callback to Timer:new(), or override Timer:tick()')
+end
+
+function timers.Timer:cancel()
+ local ok = leap.request('Timers', {op='cancel', id=self.id}).ok
+ leap.cancelreq(self.id)
+ return ok
+end
+
+function timers.Timer:isRunning()
+ return leap.request('Timers', {op='isRunning', id=self.id}).running
+end
+
+-- returns (true, seconds left) for a live timer, else (false, 0)
+function timers.Timer:timeUntilCall()
+ local result = leap.request('Timers', {op='timeUntilCall', id=self.id})
+ return result.ok, result.remaining
+end
+
+return timers