Skip to content

Commit 7a7b6c1

Browse files
committed
#4893 Tighten LLView child cache
- store cache keys as std::string to avoid dangling references - refresh parent entry on rename and skip unnamed views
1 parent 456eddd commit 7a7b6c1

File tree

2 files changed

+39
-8
lines changed

2 files changed

+39
-8
lines changed

indra/llui/llview.cpp

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,28 @@ const std::string& LLView::getName() const
253253
return mName.empty() ? no_name : mName;
254254
}
255255

256+
void LLView::setName(const std::string& name)
257+
{
258+
if (name == mName)
259+
{
260+
return;
261+
}
262+
263+
LLView* parent = mParentView;
264+
265+
if (parent && !mName.empty())
266+
{
267+
parent->mChildNameCache.erase(mName);
268+
}
269+
270+
mName = name;
271+
272+
if (parent && !mName.empty())
273+
{
274+
parent->mChildNameCache[mName] = this;
275+
}
276+
}
277+
256278
void LLView::sendChildToFront(LLView* child)
257279
{
258280
// llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs
@@ -306,7 +328,7 @@ bool LLView::addChild(LLView* child, S32 tab_group)
306328
mChildList.push_front(child);
307329

308330
// Add to name cache for fast lookup
309-
if (!child->getName().empty())
331+
if (child->hasName())
310332
{
311333
mChildNameCache[child->getName()] = child;
312334
}
@@ -352,7 +374,7 @@ void LLView::removeChild(LLView* child)
352374
mChildList.remove( child );
353375

354376
// Remove from name cache
355-
if (!child->getName().empty())
377+
if (child->hasName())
356378
{
357379
mChildNameCache.erase(child->getName());
358380
}
@@ -1663,10 +1685,14 @@ LLView* LLView::findChildView(std::string_view name, bool recurse) const
16631685
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
16641686

16651687
// Check cache first for direct children - O(1) lookup instead of O(n)
1666-
auto cache_it = mChildNameCache.find(name);
1667-
if (cache_it != mChildNameCache.end())
1688+
if (!mChildNameCache.empty())
16681689
{
1669-
return cache_it->second;
1690+
std::string lookup_key(name);
1691+
auto cache_it = mChildNameCache.find(lookup_key);
1692+
if (cache_it != mChildNameCache.end())
1693+
{
1694+
return cache_it->second;
1695+
}
16701696
}
16711697

16721698
// Look for direct children *first*
@@ -1676,7 +1702,10 @@ LLView* LLView::findChildView(std::string_view name, bool recurse) const
16761702
if (childp->getName() == name)
16771703
{
16781704
// Cache the result for next lookup
1679-
mChildNameCache[name] = childp;
1705+
if (childp->hasName())
1706+
{
1707+
mChildNameCache[childp->getName()] = childp;
1708+
}
16801709
return childp;
16811710
}
16821711
}

indra/llui/llview.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "llfocusmgr.h"
5050

5151
#include <list>
52+
#include <unordered_map>
5253
#include <boost/function.hpp>
5354
#include <boost/noncopyable.hpp>
5455

@@ -237,7 +238,8 @@ class LLView
237238
void setFollowsAll() { mReshapeFlags |= FOLLOWS_ALL; }
238239

239240
void setSoundFlags(U8 flags) { mSoundFlags = flags; }
240-
void setName(std::string name) { mName = name; }
241+
void setName(const std::string& name);
242+
bool hasName() const { return !mName.empty(); }
241243
void setUseBoundingRect( bool use_bounding_rect );
242244
bool getUseBoundingRect() const;
243245

@@ -590,7 +592,7 @@ class LLView
590592
child_list_t mChildList;
591593

592594
// Cache for fast child lookup by name - O(1) instead of O(n)
593-
mutable std::unordered_map<std::string_view, LLView*> mChildNameCache;
595+
mutable std::unordered_map<std::string, LLView*> mChildNameCache;
594596

595597
// location in pixels, relative to surrounding structure, bottom,left=0,0
596598
bool mVisible;

0 commit comments

Comments
 (0)