From bd20c548dd02778a2c7a6c318e2b8df6b2fc36c3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 2 Oct 2023 13:09:02 -0400 Subject: DRTVWR-589: Add initial integration test for LLLUAmanager. The first test runs a Lua script that calls post_on(), listen_events() and await_event() to engage in LLEventPump handshakes with the test program. Make llluamanager.cpp testable by putting LL_TEST conditionals around lots of viewer-internals headers and the lua_function definitions that engage them. Since LuaListener::connect() is called by its constructor, make it a static method that explicitly accepts the lua_State* (instead of finding it as mState). Add that parameter to its two existing calls. Add a debug log message when LuaListener is destroyed. This surfaced the need to pass a no-op deleter when listen_events() constructs a LuaListener::ptr_t. When compiled for LL_TEST, make LuaListener::mReplyPump an LLEventLogProxyFor instead of a plain LLEventStream. For debugging purposes, add a type string "LLEventLogProxy" for LLEventPumps::make(). A make() call with this type will return an LLEventLogProxyFor. --- indra/llcommon/llevents.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'indra/llcommon/llevents.cpp') diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 0a213bddef..241b8cf463 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -54,10 +54,11 @@ #pragma warning (pop) #endif // other Linden headers -#include "stringize.h" #include "llerror.h" -#include "llsdutil.h" +#include "lleventfilter.h" #include "llexception.h" +#include "llsdutil.h" +#include "stringize.h" #if LL_MSVC #pragma warning (disable : 4702) #endif @@ -71,7 +72,9 @@ LLEventPumps::LLEventPumps(): { "LLEventStream", [](const std::string& name, bool tweak) { return new LLEventStream(name, tweak); } }, { "LLEventMailDrop", [](const std::string& name, bool tweak) - { return new LLEventMailDrop(name, tweak); } } + { return new LLEventMailDrop(name, tweak); } }, + { "LLEventLogProxy", [](const std::string& name, bool tweak) + { return new LLEventLogProxyFor(name, tweak); } } }, mTypes { -- cgit v1.2.3 From 484b91dd65c8029ad5a52a6b4684d9046df709ac Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 22 Feb 2024 19:51:35 -0500 Subject: Add diagnostic logging to LLEventPumps::post(). If post() can't find the requested pump, say so. --- indra/llcommon/llevents.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'indra/llcommon/llevents.cpp') diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index deb0776887..1eeb18c40d 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -189,8 +189,13 @@ bool LLEventPumps::post(const std::string&name, const LLSD&message) PumpMap::iterator found = mPumpMap.find(name); if (found == mPumpMap.end()) + { + LL_DEBUGS("LLEventPumps") << "LLEventPump(" << std::quoted(name) << ") not found" + << LL_ENDL; return false; + } +// LL_DEBUGS("LLEventPumps") << "posting to " << name << ": " << message << LL_ENDL; return (*found).second->post(message); } @@ -405,7 +410,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL { if (!mSignal) { - LL_WARNS() << "Can't connect listener" << LL_ENDL; + LL_WARNS("LLEventPump") << "Can't connect listener" << LL_ENDL; // connect will fail, return dummy return LLBoundListener(); } -- cgit v1.2.3 From 48b20d8a2a9354469ad05b83e8b129d44ac1fdc3 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 22 Feb 2024 20:56:35 -0500 Subject: #include where std::quoted() is referenced. Remove where it isn't. --- indra/llcommon/llevents.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/llcommon/llevents.cpp') diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 1eeb18c40d..01bba7a620 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -43,6 +43,7 @@ #include #include #include +#include // std::quoted // external library headers #include #if LL_WINDOWS -- cgit v1.2.3 From de1fc577666686fb0c3f8b38d8c6c90eb6dff414 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 23 Mar 2024 17:14:33 +0900 Subject: Update sendReply(): accepting LLSD by value already copies it. --- indra/llcommon/llevents.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'indra/llcommon/llevents.cpp') diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 01bba7a620..667e047fd3 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -726,7 +726,7 @@ void LLReqID::stamp(LLSD& response) const response["reqid"] = mReqid; } -bool sendReply(const LLSD& reply, const LLSD& request, const std::string& replyKey) +bool sendReply(LLSD reply, const LLSD& request, const std::string& replyKey) { // If the original request has no value for replyKey, it's pointless to // construct or send a reply event: on which LLEventPump should we send @@ -739,13 +739,10 @@ bool sendReply(const LLSD& reply, const LLSD& request, const std::string& replyK // Here the request definitely contains replyKey; reasonable to proceed. - // Copy 'reply' to modify it. - LLSD newreply(reply); // Get the ["reqid"] element from request LLReqID reqID(request); - // and copy it to 'newreply'. - reqID.stamp(newreply); - // Send reply on LLEventPump named in request[replyKey]. Don't forget to - // send the modified 'newreply' instead of the original 'reply'. - return LLEventPumps::instance().obtain(request[replyKey]).post(newreply); + // and copy it to 'reply'. + reqID.stamp(reply); + // Send reply on LLEventPump named in request[replyKey]. + return LLEventPumps::instance().obtain(request[replyKey]).post(reply); } -- cgit v1.2.3 From 5060ccb1530ab576458aeff0d0b2b5dd24bc5880 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 9 May 2024 16:05:46 -0400 Subject: Add "Timers" LLEventAPI, actually a LazyEventAPI, for LL::Timers. Rename LL::Timers::scheduleRepeating() to scheduleEvery(). --- indra/llcommon/llevents.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'indra/llcommon/llevents.cpp') diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index d7870763cc..e10e555f8b 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -759,6 +759,9 @@ bool sendReply(LLSD reply, const LLSD& request, const std::string& replyKey) LLReqID reqID(request); // and copy it to 'reply'. reqID.stamp(reply); - // Send reply on LLEventPump named in request[replyKey]. - return LLEventPumps::instance().obtain(request[replyKey]).post(reply); + // Send reply on LLEventPump named in request[replyKey] -- if that + // LLEventPump exists. If it does not, don't create it. + // This addresses the case in which a requester goes away before a + // particular LLEventAPI responds. + return LLEventPumps::instance().post(request[replyKey], reply); } -- cgit v1.2.3 From 271bc05b91772e5aedd834db116734b34f0108a1 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 10 May 2024 09:55:19 -0400 Subject: Fix latent access violation in ~LLEventPump() if LLEventPumps gone. Instead of making LLEventPumps an LLHandleProvider, and storing an LLHandle in each LLEventPump instance, just make ~LLEventPump() query LLEventPumps::instanceExists() before calling instance(). --- indra/llcommon/llevents.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'indra/llcommon/llevents.cpp') diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index e10e555f8b..5a6e13cb7d 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -359,8 +359,7 @@ const std::string LLEventPump::ANONYMOUS = std::string(); LLEventPump::LLEventPump(const std::string& name, bool tweak): // Register every new instance with LLEventPumps - mRegistry(LLEventPumps::instance().getHandle()), - mName(mRegistry.get()->registerNew(*this, name, tweak)), + mName(LLEventPumps::instance().registerNew(*this, name, tweak)), mSignal(std::make_shared()), mEnabled(true) {} @@ -373,10 +372,9 @@ LLEventPump::~LLEventPump() { // Unregister this doomed instance from LLEventPumps -- but only if // LLEventPumps is still around! - LLEventPumps* registry = mRegistry.get(); - if (registry) + if (LLEventPumps::instanceExists()) { - registry->unregister(*this); + LLEventPumps::instance().unregister(*this); } } -- cgit v1.2.3 From 35ee96709ef2704a2636a11c67d61190dd6bdd50 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 18 Jul 2024 12:55:38 -0400 Subject: Make `LLEventPump::listen()` also accept new `LLAwareListener`. `listen()` still takes `LLEventListener`, a `callable(const LLSD&)`, but now also accepts `LLAwareListener`, a `callable(const LLBoundListener&, const LLSD&)`. This uses `boost::signals2::signal::connect_extended()`, which, when the signal is called, passes to a connected listener the `LLBoundListener` (aka `boost::signals2::connection`) representing its own connection. This allows a listener to disconnect itself when done. Internally, `listen_impl()` now always uses `connect_extended()`. When passed a classic `LLEventListener`, `listen()` wraps it in a lambda that ignores the passed `LLBoundListener`. `listen()` also now accepts `LLVoidListener`, and internally wraps it in a lambda that returns `false` on its behalf. --- indra/llcommon/llevents.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'indra/llcommon/llevents.cpp') diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 5a6e13cb7d..98bd990f31 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -415,7 +415,7 @@ void LLEventPump::reset() //mDeps.clear(); } -LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventListener& listener, +LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLAwareListener& listener, const NameList& after, const NameList& before) { @@ -575,7 +575,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL } // Now that newNode has a value that places it appropriately in mSignal, // connect it. - LLBoundListener bound = mSignal->connect(nodePosition, listener); + LLBoundListener bound = mSignal->connect_extended(nodePosition, listener); if (!name.empty()) { // note that we are not tracking anonymous listeners here either. @@ -659,7 +659,7 @@ bool LLEventMailDrop::post(const LLSD& event) } LLBoundListener LLEventMailDrop::listen_impl(const std::string& name, - const LLEventListener& listener, + const LLAwareListener& listener, const NameList& after, const NameList& before) { @@ -668,7 +668,10 @@ LLBoundListener LLEventMailDrop::listen_impl(const std::string& name, // Remove any that this listener consumes -- Effective STL, Item 9. for (auto hi(mEventHistory.begin()), hend(mEventHistory.end()); hi != hend; ) { - if (listener(*hi)) + // We don't actually have an LLBoundListener in hand, and we won't + // until the base-class listen_impl() call below. Pass an empty + // instance. + if (listener({}, *hi)) { // new listener consumed this event, erase it hi = mEventHistory.erase(hi); -- cgit v1.2.3 From 03d7f2b84daf9ab991de6cad7d6149abda1ef716 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 28 Aug 2024 21:16:56 -0400 Subject: Ditch trailing spaces. --- indra/llcommon/llevents.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'indra/llcommon/llevents.cpp') diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 0338fd53e5..a694f0dc7f 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -3,25 +3,25 @@ * @author Nat Goodspeed * @date 2008-09-12 * @brief Implementation for llevents. - * + * * $LicenseInfo:firstyear=2008&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$ */ @@ -430,8 +430,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLAwareL float nodePosition = 1.0; - // if the supplied name is empty we are not interested in the ordering mechanism - // and can bypass attempting to find the optimal location to insert the new + // if the supplied name is empty we are not interested in the ordering mechanism + // and can bypass attempting to find the optimal location to insert the new // listener. We'll just tack it on to the end. if (!name.empty()) // should be the same as testing against ANONYMOUS { @@ -576,12 +576,12 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLAwareL // Now that newNode has a value that places it appropriately in mSignal, // connect it. LLBoundListener bound = mSignal->connect_extended(nodePosition, listener); - + if (!name.empty()) { // note that we are not tracking anonymous listeners here either. - // This means that it is the caller's responsibility to either assign - // to a TempBoundListerer (scoped_connection) or manually disconnect - // when done. + // This means that it is the caller's responsibility to either assign + // to a TempBoundListerer (scoped_connection) or manually disconnect + // when done. mConnections[name] = bound; } return bound; @@ -648,9 +648,9 @@ bool LLEventMailDrop::post(const LLSD& event) { // forward the call to our base class bool posted = LLEventStream::post(event); - + if (!posted) - { // if the event was not handled we will save it for later so that it can + { // if the event was not handled we will save it for later so that it can // be posted to any future listeners when they attach. mEventHistory.push_back(event); } -- cgit v1.2.3 From ea24ac899ca28a587be0e187b77873a25d08a556 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 4 Sep 2024 14:07:26 -0400 Subject: Extract coroutine-aware synchronization primitives to new header. Changes on new main and changes on Lua project branch combined into a header circularity. Resolved by hoisting coroutine-aware synchronization primitives out to a new llcoromutex.h file in the `llcoro` namespace, rather than being literally members of the `LLCoros` class. But retained `using` declarations in `LLCoros` for backwards compatibility. --- indra/llcommon/llevents.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/llcommon/llevents.cpp') diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index a694f0dc7f..6531b951b9 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -389,7 +389,7 @@ std::string LLEventPump::inventName(const std::string& pfx) void LLEventPump::clear() { - LLCoros::LockType lock(mConnectionListMutex); + llcoro::LockType lock(mConnectionListMutex); // Destroy the original LLStandardSignal instance, replacing it with a // whole new one. mSignal = std::make_shared(); @@ -401,7 +401,7 @@ void LLEventPump::reset() { // Resetting mSignal is supposed to disconnect everything on its own // But due to crash on 'reset' added explicit cleanup to get more data - LLCoros::LockType lock(mConnectionListMutex); + llcoro::LockType lock(mConnectionListMutex); ConnectionMap::const_iterator iter = mConnections.begin(); ConnectionMap::const_iterator end = mConnections.end(); while (iter!=end) @@ -426,7 +426,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLAwareL return LLBoundListener(); } - LLCoros::LockType lock(mConnectionListMutex); + llcoro::LockType lock(mConnectionListMutex); float nodePosition = 1.0; @@ -589,7 +589,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLAwareL LLBoundListener LLEventPump::getListener(const std::string& name) { - LLCoros::LockType lock(mConnectionListMutex); + llcoro::LockType lock(mConnectionListMutex); ConnectionMap::const_iterator found = mConnections.find(name); if (found != mConnections.end()) { @@ -601,7 +601,7 @@ LLBoundListener LLEventPump::getListener(const std::string& name) void LLEventPump::stopListening(const std::string& name) { - LLCoros::LockType lock(mConnectionListMutex); + llcoro::LockType lock(mConnectionListMutex); ConnectionMap::iterator found = mConnections.find(name); if (found != mConnections.end()) { -- cgit v1.2.3