4040#include " llinventorymodel.h"
4141#include " llviewerinventory.h"
4242
43+ bool LLInventoryItemsList::sListIdleRegistered = false ;
44+ LLInventoryItemsList::all_list_t LLInventoryItemsList::sAllLists ;
45+ LLInventoryItemsList::all_list_t ::iterator LLInventoryItemsList::sAllListIter ;
46+
4347LLInventoryItemsList::Params::Params ()
4448{}
4549
@@ -55,13 +59,39 @@ LLInventoryItemsList::LLInventoryItemsList(const LLInventoryItemsList::Params& p
5559
5660 setNoFilteredItemsMsg (LLTrans::getString (" InventoryNoMatchingItems" ));
5761
58- gIdleCallbacks .addFunction (idle, this );
62+ sAllLists .push_back (this );
63+ sAllListIter = sAllLists .begin ();
64+
65+ if (!sListIdleRegistered )
66+ {
67+ sAllListIter = sAllLists .begin ();
68+ gIdleCallbacks .addFunction (idle, nullptr );
69+
70+ LLEventPumps::instance ().obtain (" LLApp" ).listen (
71+ " LLInventoryItemsList" ,
72+ [](const LLSD& stat)
73+ {
74+ std::string status (stat[" status" ]);
75+ if (status != " running" )
76+ {
77+ // viewer is starting shutdown
78+ gIdleCallbacks .deleteFunction (idle, nullptr );
79+ }
80+ return false ;
81+ });
82+ sListIdleRegistered = true ;
83+ }
5984}
6085
6186// virtual
6287LLInventoryItemsList::~LLInventoryItemsList ()
6388{
64- gIdleCallbacks .deleteFunction (idle, this );
89+ auto it = std::find (sAllLists .begin (), sAllLists .end (), this );
90+ if (it != sAllLists .end ())
91+ {
92+ sAllLists .erase (it);
93+ sAllListIter = sAllLists .begin ();
94+ }
6595}
6696
6797void LLInventoryItemsList::refreshList (const LLInventoryModel::item_array_t item_array)
@@ -111,25 +141,55 @@ void LLInventoryItemsList::updateSelection()
111141 mSelectTheseIDs .clear ();
112142}
113143
114- void LLInventoryItemsList::doIdle ()
144+ bool LLInventoryItemsList::doIdle ()
115145{
116- if (mRefreshState == REFRESH_COMPLETE) return ;
146+ if (mRefreshState == REFRESH_COMPLETE) return true ; // done
117147
118148 if (isInVisibleChain () || mForceRefresh || !getFilterSubString ().empty ())
119149 {
120150 refresh ();
121151
122152 mRefreshCompleteSignal (this , LLSD ());
153+ return false ; // keep going
123154 }
155+ return true ; // done
124156}
125157
126158// static
127159void LLInventoryItemsList::idle (void * user_data)
128160{
129- LLInventoryItemsList* self = static_cast <LLInventoryItemsList*>(user_data);
130- if ( self )
131- { // Do the real idle
132- self->doIdle ();
161+ if (sAllLists .empty ())
162+ return ;
163+
164+ LL_PROFILE_ZONE_SCOPED;
165+
166+ using namespace std ::chrono;
167+ auto start = steady_clock::now ();
168+ const milliseconds time_limit = milliseconds (3 );
169+ const auto end_time = start + time_limit;
170+ S32 max_update_count = 50 ;
171+
172+ if (sAllListIter == sAllLists .end ())
173+ {
174+ sAllListIter = sAllLists .begin ();
175+ }
176+
177+ S32 updated = 0 ;
178+ while (steady_clock::now () < end_time
179+ && updated < max_update_count
180+ && sAllListIter != sAllLists .end ())
181+ {
182+ LLInventoryItemsList* list = *sAllListIter ;
183+ // Refresh is split into multiple separate parts,
184+ // so keep repeating it while there is time, until done.
185+ // Todo: refresh() split is pointless now?
186+ // Or still useful for large folders?
187+ if (list->doIdle ())
188+ {
189+ // Item is done
190+ ++sAllListIter ;
191+ updated++;
192+ }
133193 }
134194}
135195
@@ -141,6 +201,7 @@ void LLInventoryItemsList::refresh()
141201 {
142202 case REFRESH_ALL:
143203 {
204+ LL_PROFILE_ZONE_NAMED (" items_refresh_all" );
144205 mAddedItems .clear ();
145206 mRemovedItems .clear ();
146207 computeDifference (getIDs (), mAddedItems , mRemovedItems );
@@ -163,6 +224,7 @@ void LLInventoryItemsList::refresh()
163224 }
164225 case REFRESH_LIST_ERASE:
165226 {
227+ LL_PROFILE_ZONE_NAMED (" items_refresh_erase" );
166228 uuid_vec_t ::const_iterator it = mRemovedItems .begin ();
167229 for (; mRemovedItems .end () != it; ++it)
168230 {
@@ -175,6 +237,7 @@ void LLInventoryItemsList::refresh()
175237 }
176238 case REFRESH_LIST_APPEND:
177239 {
240+ LL_PROFILE_ZONE_NAMED (" items_refresh_append" );
178241 static const unsigned ADD_LIMIT = 25 ; // Note: affects perfomance
179242
180243 unsigned int nadded = 0 ;
@@ -239,6 +302,7 @@ void LLInventoryItemsList::refresh()
239302 }
240303 case REFRESH_LIST_SORT:
241304 {
305+ LL_PROFILE_ZONE_NAMED (" items_refresh_sort" );
242306 // Filter, sort, rearrange and notify parent about shape changes
243307 filterItems (true , true );
244308
@@ -255,7 +319,10 @@ void LLInventoryItemsList::refresh()
255319 break ;
256320 }
257321 default :
258- break ;
322+ {
323+ mRefreshState = REFRESH_COMPLETE;
324+ break ;
325+ }
259326 }
260327
261328 setForceRefresh (mRefreshState != REFRESH_COMPLETE);
0 commit comments