From d44e5b7d9cd22e372ce19aa1d4f62904d13ed97e Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 6 Mar 2015 15:57:11 -0500 Subject: SL-103 WIP - comment re: possible future work --- indra/llui/llfolderview.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/llui') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 474b545f00..3ec92cb6e7 100755 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1809,7 +1809,9 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) } // Successively filter out invalid options - + // FIXME this item-by-item approach does not allow options to be enabled/disabled based on the selection as a whole - for example, + // if avatar has room for one more wearable, and the selection includes two wearables, add should be disabled. + // llwearableitemslist.cpp has a more holistic approach here. U32 multi_select_flag = (mSelectedItems.size() > 1 ? ITEM_IN_MULTI_SELECTION : 0x0); U32 flags = multi_select_flag | FIRST_SELECTED_ITEM; for (selected_items_t::iterator item_itor = mSelectedItems.begin(); -- cgit v1.3 From 64511ce28f4c3740fe7f87d680722105f83f82c0 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 6 Mar 2015 16:05:47 -0500 Subject: SL-103 WIP - comment --- indra/llui/llfolderview.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 3ec92cb6e7..26cb90505d 100755 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1808,10 +1808,15 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) (*menu_itor)->setEnabled(TRUE); } + + // FIXME this item-by-item approach does not allow options to be + // enabled/disabled based on the selection as a whole - for + // example, if avatar has room for one more wearable, and the + // selection includes two wearables, add should be disabled. + // canAddWearables() in llwearableitemslist.cpp has a more + // holistic approach to this. + // Successively filter out invalid options - // FIXME this item-by-item approach does not allow options to be enabled/disabled based on the selection as a whole - for example, - // if avatar has room for one more wearable, and the selection includes two wearables, add should be disabled. - // llwearableitemslist.cpp has a more holistic approach here. U32 multi_select_flag = (mSelectedItems.size() > 1 ? ITEM_IN_MULTI_SELECTION : 0x0); U32 flags = multi_select_flag | FIRST_SELECTED_ITEM; for (selected_items_t::iterator item_itor = mSelectedItems.begin(); -- cgit v1.3 From fb072c91485a484e3d0740113ee753b58c439900 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 13 Mar 2015 16:38:23 -0400 Subject: MAINT-4980 WIP - add context menu filtering based on the selection group --- indra/llui/llfolderview.cpp | 16 ++++++- indra/llui/llfolderview.h | 8 +++- indra/llui/llfolderviewitem.h | 7 +++ indra/newview/llinventorybridge.cpp | 86 ++++++++++++++++++++++++++++++++++++- indra/newview/llinventorybridge.h | 8 ++++ indra/newview/llinventorypanel.cpp | 4 +- indra/newview/llinventorypanel.h | 2 + indra/newview/llwearableitemslist.h | 3 +- 8 files changed, 129 insertions(+), 5 deletions(-) mode change 100644 => 100755 indra/llui/llfolderviewitem.h (limited to 'indra/llui') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 26cb90505d..7f0d486981 100755 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -171,7 +171,8 @@ LLFolderView::LLFolderView(const Params& p) mDraggingOverItem(NULL), mStatusTextBox(NULL), mShowItemLinkOverlays(p.show_item_link_overlays), - mViewModel(p.view_model) + mViewModel(p.view_model), + mGroupedItemModel(p.grouped_item_model) { claimMem(mViewModel); LLPanel* panel = p.parent_panel; @@ -1828,6 +1829,19 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) flags = multi_select_flag; } + if (getFolderViewGroupedItemModel()) + { + getFolderViewGroupedItemModel()->groupFilterContextMenu(mSelectedItems,*menu); + } +#if 0 + selected_items_t::iterator item_itor = mSelectedItems.begin(); + if (item_itor != mSelectedItems.end()) + { + LLFolderViewItem* selected_item = (*item_itor); + selected_item->getViewModelItem()->groupFilterContextMenu(mSelectedItems,*menu); + } +#endif + addNoOptions(menu); } diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 08e0a6220a..114dd7bd2f 100755 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -45,6 +45,7 @@ #include "llscrollcontainer.h" class LLFolderViewModelInterface; +class LLFolderViewGroupedItemModel; class LLFolderViewFolder; class LLFolderViewItem; class LLFolderViewFilter; @@ -93,6 +94,7 @@ public: use_ellipses, show_item_link_overlays; Mandatory view_model; + Optional grouped_item_model; Mandatory options_menu; @@ -100,7 +102,7 @@ public: }; friend class LLFolderViewScrollContainer; - typedef std::deque selected_items_t; + typedef folder_view_item_deque selected_items_t; LLFolderView(const Params&); virtual ~LLFolderView( void ); @@ -113,6 +115,9 @@ public: LLFolderViewModelInterface* getFolderViewModel() { return mViewModel; } const LLFolderViewModelInterface* getFolderViewModel() const { return mViewModel; } + LLFolderViewGroupedItemModel* getFolderViewGroupedItemModel() { return mGroupedItemModel; } + const LLFolderViewGroupedItemModel* getFolderViewGroupedItemModel() const { return mGroupedItemModel; } + typedef boost::signals2::signal& items, BOOL user_action)> signal_t; void setSelectCallback(const signal_t::slot_type& cb) { mSelectSignal.connect(cb); } void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } @@ -300,6 +305,7 @@ protected: LLHandle mParentPanel; LLFolderViewModelInterface* mViewModel; + LLFolderViewGroupedItemModel* mGroupedItemModel; /** * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll. diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h old mode 100644 new mode 100755 index 0cd20a0f2d..5ad5731cad --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h @@ -454,5 +454,12 @@ public: template void sortItems(const SORT_FUNC& func) { mItems.sort(func); } }; +typedef std::deque folder_view_item_deque; + +class LLFolderViewGroupedItemModel: public LLRefCount +{ +public: + virtual void groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu) = 0; +}; #endif // LLFOLDERVIEWITEM_H diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 958bc7d558..3ec8bb0ab9 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -74,6 +74,7 @@ #include "llviewerwindow.h" #include "llvoavatarself.h" #include "llwearablelist.h" +#include "llwearableitemslist.h" #include "lllandmarkactions.h" #include "llpanellandmarks.h" @@ -557,6 +558,46 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const return TRUE; } +void disable_context_entries_if_present(LLMenuGL& menu, + const menuentry_vec_t &disabled_entries) +{ + const LLView::child_list_t *list = menu.getChildList(); + for (LLView::child_list_t::const_iterator itor = list->begin(); + itor != list->end(); + ++itor) + { + LLView *menu_item = (*itor); + std::string name = menu_item->getName(); + + // descend into split menus: + LLMenuItemBranchGL* branchp = dynamic_cast(menu_item); + if ((name == "More") && branchp) + { + disable_context_entries_if_present(*branchp->getBranch(), disabled_entries); + } + + bool found = false; + menuentry_vec_t::const_iterator itor2; + for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2) + { + if (*itor2 == name) + { + found = true; + break; + } + } + + if (found) + { + menu_item->setVisible(TRUE); + // A bit of a hack so we can remember that some UI element explicitly set this to be visible + // so that some other UI element from multi-select doesn't later set this invisible. + menu_item->pushVisible(TRUE); + + menu_item->setEnabled(FALSE); + } + } +} void hide_context_entries(LLMenuGL& menu, const menuentry_vec_t &entries_to_show, const menuentry_vec_t &disabled_entries) @@ -765,6 +806,31 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) hide_context_entries(menu, items, disabled_items); } +bool get_selection_item_uuids(LLFolderView::selected_items_t& selected_items, uuid_vec_t& ids) +{ + uuid_vec_t results; + S32 non_item = 0; + for(LLFolderView::selected_items_t::iterator it = selected_items.begin(); it != selected_items.end(); ++it) + { + LLItemBridge *view_model = dynamic_cast((*it)->getViewModelItem()); + + if(view_model && view_model->getUUID().notNull()) + { + results.push_back(view_model->getUUID()); + } + else + { + non_item++; + } + } + if (non_item == 0) + { + ids = results; + return true; + } + return false; +} + void LLInvFVBridge::addTrashContextMenuOptions(menuentry_vec_t &items, menuentry_vec_t &disabled_items) { @@ -3585,7 +3651,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(!model) return; buildContextMenuOptions(flags, items, disabled_items); - hide_context_entries(menu, items, disabled_items); + hide_context_entries(menu, items, disabled_items); // Reposition the menu, in case we're adding items to an existing menu. menu.needsArrange(); @@ -6439,4 +6505,22 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge( return new_listener; } +LLFolderViewGroupedItemBridge::LLFolderViewGroupedItemBridge() +{ +} + +void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu) +{ + uuid_vec_t ids; + menuentry_vec_t disabled_items; + if (get_selection_item_uuids(selected_items, ids)) + { + if (!LLWearableItemsList::ContextMenu::canAddWearables(ids)) + { + disabled_items.push_back(std::string("Wearable Add")); + } + } + disable_context_entries_if_present(menu, disabled_items); +} + // EOF diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index e8d5db4437..6a8478e64b 100755 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -37,6 +37,7 @@ #include "llviewerwearable.h" #include "lltooldraganddrop.h" #include "lllandmarklist.h" +#include "llfolderviewitem.h" class LLInventoryFilter; class LLInventoryPanel; @@ -687,4 +688,11 @@ void hide_context_entries(LLMenuGL& menu, const menuentry_vec_t &entries_to_show, const menuentry_vec_t &disabled_entries); +class LLFolderViewGroupedItemBridge: public LLFolderViewGroupedItemModel +{ +public: + LLFolderViewGroupedItemBridge(); + virtual void groupFilterContextMenu(folder_view_item_deque& selected_items, LLMenuGL& menu); +}; + #endif // LL_LLINVENTORYBRIDGE_H diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 3546317471..4a230accb6 100755 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -146,7 +146,8 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : mShowEmptyMessage(p.show_empty_message), mViewsInitialized(false), mInvFVBridgeBuilder(NULL), - mInventoryViewModel(p.name) + mInventoryViewModel(p.name), + mGroupedItemBridge(new LLFolderViewGroupedItemBridge) { mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER; @@ -186,6 +187,7 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id ) NULL, root_id); p.view_model = &mInventoryViewModel; + p.grouped_item_model = mGroupedItemBridge; p.use_label_suffix = mParams.use_label_suffix; p.allow_multiselect = mAllowMultiSelect; p.show_empty_message = mShowEmptyMessage; diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index a490dfce5d..bc4c10e441 100755 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -43,6 +43,7 @@ class LLInvFVBridge; class LLInventoryFolderViewModelBuilder; class LLInvPanelComplObserver; class LLFolderViewModelInventory; +class LLFolderViewGroupedItemBridge; namespace LLInitParam { @@ -240,6 +241,7 @@ protected: LLScrollContainer* mScroller; LLFolderViewModelInventory mInventoryViewModel; + LLPointer mGroupedItemBridge; Params mParams; // stored copy of parameter block std::map mItemMap; diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index 58a00c5be0..eb975b6301 100755 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -410,6 +410,8 @@ public: ContextMenu(); /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y); + // FIXME logic should live somewhere more generally useful. + static bool canAddWearables(const uuid_vec_t& item_ids); protected: enum { MASK_CLOTHING = 0x01, @@ -425,7 +427,6 @@ public: static void setMenuItemEnabled(LLContextMenu* menu, const std::string& name, bool val); static void updateMask(U32& mask, LLAssetType::EType at); static void createNewWearable(const LLUUID& item_id); - static bool canAddWearables(const uuid_vec_t& item_ids); LLWearableItemsList* mParent; }; -- cgit v1.3 From dd7f0e2954a80e39eba50b7a06e167a50a248632 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 13 Mar 2015 16:55:19 -0400 Subject: MAINT-4980 WIP - moved canAddWearables() to LLAppearanceMgr --- indra/llui/llfolderview.cpp | 21 +++------------ indra/newview/llappearancemgr.cpp | 43 +++++++++++++++++++++++++++++++ indra/newview/llappearancemgr.h | 3 +++ indra/newview/llinventorybridge.cpp | 2 +- indra/newview/llwearableitemslist.cpp | 48 ++--------------------------------- indra/newview/llwearableitemslist.h | 2 -- 6 files changed, 53 insertions(+), 66 deletions(-) (limited to 'indra/llui') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 7f0d486981..0fb163c73a 100755 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1809,14 +1809,6 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) (*menu_itor)->setEnabled(TRUE); } - - // FIXME this item-by-item approach does not allow options to be - // enabled/disabled based on the selection as a whole - for - // example, if avatar has room for one more wearable, and the - // selection includes two wearables, add should be disabled. - // canAddWearables() in llwearableitemslist.cpp has a more - // holistic approach to this. - // Successively filter out invalid options U32 multi_select_flag = (mSelectedItems.size() > 1 ? ITEM_IN_MULTI_SELECTION : 0x0); U32 flags = multi_select_flag | FIRST_SELECTED_ITEM; @@ -1829,19 +1821,14 @@ void LLFolderView::updateMenuOptions(LLMenuGL* menu) flags = multi_select_flag; } + // This adds a check for restrictions based on the entire + // selection set - for example, any one wearable may not push you + // over the limit, but all wearables together still might. if (getFolderViewGroupedItemModel()) { getFolderViewGroupedItemModel()->groupFilterContextMenu(mSelectedItems,*menu); } -#if 0 - selected_items_t::iterator item_itor = mSelectedItems.begin(); - if (item_itor != mSelectedItems.end()) - { - LLFolderViewItem* selected_item = (*item_itor); - selected_item->getViewModelItem()->groupFilterContextMenu(mSelectedItems,*menu); - } -#endif - + addNoOptions(menu); } diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index b5af1af5bc..2c166b6001 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1782,6 +1782,49 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id) return items.size() > 0; } +// Moved from LLWearableList::ContextMenu for wider utility. +bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids) +{ + // TODO: investigate wearables may not be loaded at this point EXT-8231 + + U32 n_objects = 0; + U32 n_clothes = 0; + + // Count given clothes (by wearable type) and objects. + for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it) + { + LLViewerInventoryItem* item = gInventory.getItem(*it); + if (!item) + { + return false; + } + + if (item->getType() == LLAssetType::AT_OBJECT) + { + ++n_objects; + } + else if (item->getType() == LLAssetType::AT_CLOTHING) + { + ++n_clothes; + } + else + { + LL_WARNS() << "Unexpected wearable type" << LL_ENDL; + return false; + } + } + + // Check whether we can add all the objects. + if (!isAgentAvatarValid() || !gAgentAvatarp->canAttachMoreObjects(n_objects)) + { + return false; + } + + // Check whether we can add all the clothes. + U32 sum_clothes = n_clothes + gAgentWearables.getClothingLayerCount(); + return sum_clothes <= LLAgentWearables::MAX_CLOTHING_LAYERS; +} + void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer cb) { LLInventoryModel::cat_array_t cats; diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 399cd6388f..10d97bb8cb 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -100,6 +100,9 @@ public: // Determine whether we can replace current outfit with the given one. bool getCanReplaceCOF(const LLUUID& outfit_cat_id); + // Can we add all referenced items to the avatar? + bool canAddWearables(const uuid_vec_t& item_ids); + // Copy all items in a category. void shallowCopyCategoryContents(const LLUUID& src_id, const LLUUID& dst_id, LLPointer cb); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 3ec8bb0ab9..cd45d0a4f3 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -6515,7 +6515,7 @@ void LLFolderViewGroupedItemBridge::groupFilterContextMenu(folder_view_item_dequ menuentry_vec_t disabled_items; if (get_selection_item_uuids(selected_items, ids)) { - if (!LLWearableItemsList::ContextMenu::canAddWearables(ids)) + if (!LLAppearanceMgr::instance().canAddWearables(ids)) { disabled_items.push_back(std::string("Wearable Add")); } diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 98559e7782..888ead0613 100755 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -894,13 +894,13 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu setMenuItemVisible(menu, "wear_wear", n_already_worn == 0 && n_worn == 0 && can_be_worn); setMenuItemEnabled(menu, "wear_wear", n_already_worn == 0 && n_worn == 0); setMenuItemVisible(menu, "wear_add", wear_add_visible); - setMenuItemEnabled(menu, "wear_add", canAddWearables(ids)); + setMenuItemEnabled(menu, "wear_add", LLAppearanceMgr::instance().canAddWearables(ids)); setMenuItemVisible(menu, "wear_replace", n_worn == 0 && n_already_worn != 0 && can_be_worn); //visible only when one item selected and this item is worn setMenuItemVisible(menu, "edit", !standalone && mask & (MASK_CLOTHING|MASK_BODYPART) && n_worn == n_items && n_worn == 1); setMenuItemEnabled(menu, "edit", n_editable == 1 && n_worn == 1 && n_items == 1); setMenuItemVisible(menu, "create_new", mask & (MASK_CLOTHING|MASK_BODYPART) && n_items == 1); - setMenuItemEnabled(menu, "create_new", canAddWearables(ids)); + setMenuItemEnabled(menu, "create_new", LLAppearanceMgr::instance().canAddWearables(ids)); setMenuItemVisible(menu, "show_original", !standalone); setMenuItemEnabled(menu, "show_original", n_items == 1 && n_links == n_items); setMenuItemVisible(menu, "take_off", mask == MASK_CLOTHING && n_worn == n_items); @@ -1004,48 +1004,4 @@ void LLWearableItemsList::ContextMenu::createNewWearable(const LLUUID& item_id) LLAgentWearables::createWearable(item->getWearableType(), true); } -// Returns true if all the given objects and clothes can be added. -// static -bool LLWearableItemsList::ContextMenu::canAddWearables(const uuid_vec_t& item_ids) -{ - // TODO: investigate wearables may not be loaded at this point EXT-8231 - - U32 n_objects = 0; - U32 n_clothes = 0; - - // Count given clothes (by wearable type) and objects. - for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it) - { - LLViewerInventoryItem* item = gInventory.getItem(*it); - if (!item) - { - return false; - } - - if (item->getType() == LLAssetType::AT_OBJECT) - { - ++n_objects; - } - else if (item->getType() == LLAssetType::AT_CLOTHING) - { - ++n_clothes; - } - else - { - LL_WARNS() << "Unexpected wearable type" << LL_ENDL; - return false; - } - } - - // Check whether we can add all the objects. - if (!isAgentAvatarValid() || !gAgentAvatarp->canAttachMoreObjects(n_objects)) - { - return false; - } - - // Check whether we can add all the clothes. - U32 sum_clothes = n_clothes + gAgentWearables.getClothingLayerCount(); - return sum_clothes <= LLAgentWearables::MAX_CLOTHING_LAYERS; -} - // EOF diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index eb975b6301..715c249616 100755 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -410,8 +410,6 @@ public: ContextMenu(); /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y); - // FIXME logic should live somewhere more generally useful. - static bool canAddWearables(const uuid_vec_t& item_ids); protected: enum { MASK_CLOTHING = 0x01, -- cgit v1.3 From 107b9bcb70e785c2d12515e38b8b296eea7ab8d8 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 20 May 2015 10:56:09 -0400 Subject: MAINT-5232: Introduce SUBSYSTEM_CLEANUP() macro and use it for existing LLSomeClass::cleanupClass() calls. This logs the fact of making the call, as well as making it. --- .../llimage_libtest/llimage_libtest.cpp | 3 +- indra/llcommon/llapp.cpp | 3 +- indra/llcommon/llcleanup.h | 30 +++++++++++++++ indra/llcommon/llcommon.cpp | 5 ++- indra/llcorehttp/tests/llcorehttp_test.cpp | 3 +- indra/llcrashlogger/llcrashlogger.cpp | 3 +- indra/llmessage/tests/llhttpclient_test.cpp | 3 +- indra/llui/llui.cpp | 3 +- indra/newview/llappviewer.cpp | 43 +++++++++++----------- indra/newview/llstartup.cpp | 3 +- indra/newview/llviewermenu.cpp | 3 +- indra/newview/llviewerobject.cpp | 11 +++--- indra/newview/llviewerwindow.cpp | 7 ++-- indra/newview/pipeline.cpp | 3 +- 14 files changed, 83 insertions(+), 40 deletions(-) create mode 100644 indra/llcommon/llcleanup.h (limited to 'indra/llui') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 3d27b4a5b5..f4dba16a94 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -42,6 +42,7 @@ #include "lldiriterator.h" #include "v4coloru.h" #include "llsdserialize.h" +#include "llcleanup.h" // system libraries #include @@ -634,7 +635,7 @@ int main(int argc, char** argv) } // Cleanup and exit - LLImage::cleanupClass(); + SUBSYSTEM_CLEANUP(LLImage); if (fast_timer_log_thread) { fast_timer_log_thread->shutdown(); diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 5a40845e7d..2c52b11594 100755 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -48,6 +48,7 @@ #include "lleventtimer.h" #include "google_breakpad/exception_handler.h" #include "stringize.h" +#include "llcleanup.h" // // Signal handling @@ -177,7 +178,7 @@ LLApp::~LLApp() if(mExceptionHandler != 0) delete mExceptionHandler; - LLCommon::cleanupClass(); + SUBSYSTEM_CLEANUP(LLCommon); } // static diff --git a/indra/llcommon/llcleanup.h b/indra/llcommon/llcleanup.h new file mode 100644 index 0000000000..8eda9a7fb3 --- /dev/null +++ b/indra/llcommon/llcleanup.h @@ -0,0 +1,30 @@ +/** + * @file llcleanup.h + * @author Nat Goodspeed + * @date 2015-05-20 + * @brief Mechanism for cleaning up subsystem resources + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Copyright (c) 2015, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLCLEANUP_H) +#define LL_LLCLEANUP_H + +#include "llerror.h" + +// Instead of directly calling SomeClass::cleanupClass(), use +// SUBSYSTEM_CLEANUP(SomeClass); +// This logs the call as well as performing it. That gives us a baseline +// subsystem shutdown order against which to compare subsequent dynamic +// shutdown schemes. +#define SUBSYSTEM_CLEANUP(CLASSNAME) \ + do { \ + LL_INFOS("Cleanup") << "Calling " #CLASSNAME "::cleanupClass()" << LL_ENDL; \ + CLASSNAME::cleanupClass(); \ + } while (0) +// Use ancient do { ... } while (0) macro trick to permit a block of +// statements with the same syntax as a single statement. + +#endif /* ! defined(LL_LLCLEANUP_H) */ diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 19642b0982..439ff4e628 100755 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -31,6 +31,7 @@ #include "llthread.h" #include "lltrace.h" #include "lltracethreadrecorder.h" +#include "llcleanup.h" //static BOOL LLCommon::sAprInitialized = FALSE; @@ -63,11 +64,11 @@ void LLCommon::cleanupClass() sMasterThreadRecorder = NULL; LLTrace::set_master_thread_recorder(NULL); LLThreadSafeRefCount::cleanupThreadSafeRefCount(); - LLTimer::cleanupClass(); + SUBSYSTEM_CLEANUP(LLTimer); if (sAprInitialized) { ll_cleanup_apr(); sAprInitialized = FALSE; } - LLMemory::cleanupClass(); + SUBSYSTEM_CLEANUP(LLMemory); } diff --git a/indra/llcorehttp/tests/llcorehttp_test.cpp b/indra/llcorehttp/tests/llcorehttp_test.cpp index e863ddd13f..19a20e663c 100755 --- a/indra/llcorehttp/tests/llcorehttp_test.cpp +++ b/indra/llcorehttp/tests/llcorehttp_test.cpp @@ -46,6 +46,7 @@ #include "test_httprequestqueue.hpp" #include "llproxy.h" +#include "llcleanup.h" unsigned long ssl_thread_id_callback(void); void ssl_locking_callback(int mode, int type, const char * file, int line); @@ -101,7 +102,7 @@ void init_curl() void term_curl() { - LLProxy::cleanupClass(); + SUBSYSTEM_CLEANUP(LLProxy); CRYPTO_set_locking_callback(NULL); for (int i(0); i < ssl_mutex_count; ++i) diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 7a97c16ea7..0d239c9435 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -45,6 +45,7 @@ #include "llhttpclient.h" #include "llsdserialize.h" #include "llproxy.h" +#include "llcleanup.h" LLPumpIO* gServicePump = NULL; BOOL gBreak = false; @@ -587,5 +588,5 @@ bool LLCrashLogger::init() void LLCrashLogger::commonCleanup() { LLError::logToFile(""); //close crashreport.log - LLProxy::cleanupClass(); + SUBSYSTEM_CLEANUP(LLProxy); } diff --git a/indra/llmessage/tests/llhttpclient_test.cpp b/indra/llmessage/tests/llhttpclient_test.cpp index a32bfa59ce..9356a14f1f 100755 --- a/indra/llmessage/tests/llhttpclient_test.cpp +++ b/indra/llmessage/tests/llhttpclient_test.cpp @@ -42,6 +42,7 @@ #include "lliosocket.h" #include "stringize.h" +#include "llcleanup.h" namespace tut { @@ -66,7 +67,7 @@ namespace tut ~HTTPClientTestData() { delete mClientPump; - LLProxy::cleanupClass(); + SUBSYSTEM_CLEANUP(LLProxy); apr_pool_destroy(mPool); } diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index aabc7ed2e4..cc186f4997 100755 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -60,6 +60,7 @@ #include "llflyoutbutton.h" #include "llsearcheditor.h" #include "lltoolbar.h" +#include "llcleanup.h" // for XUIParse #include "llquaternion.h" @@ -208,7 +209,7 @@ void LLUI::initClass(const settings_map_t& settings, void LLUI::cleanupClass() { - LLRender2D::cleanupClass(); + SUBSYSTEM_CLEANUP(LLRender2D); } void LLUI::setPopupFuncs(const add_popup_t& add_popup, const remove_popup_t& remove_popup, const clear_popups_t& clear_popups) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 6dc71bc94e..6a64f67f9c 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -226,6 +226,7 @@ #include "llsecapi.h" #include "llmachineid.h" #include "llmainlooprepeater.h" +#include "llcleanup.h" #include "llviewereventrecorder.h" @@ -1764,7 +1765,7 @@ bool LLAppViewer::cleanup() gTransferManager.cleanup(); #endif - LLLocalBitmapMgr::cleanupClass(); + SUBSYSTEM_CLEANUP(LLLocalBitmapMgr); // Note: this is where gWorldMap used to be deleted. @@ -1872,11 +1873,11 @@ bool LLAppViewer::cleanup() LLViewerObject::cleanupVOClasses(); - LLAvatarAppearance::cleanupClass(); + SUBSYSTEM_CLEANUP(LLAvatarAppearance); - LLAvatarAppearance::cleanupClass(); + SUBSYSTEM_CLEANUP(LLAvatarAppearance); - LLPostProcess::cleanupClass(); + SUBSYSTEM_CLEANUP(LLPostProcess); LLTracker::cleanupInstance(); @@ -1902,12 +1903,12 @@ bool LLAppViewer::cleanup() //end_messaging_system(); - LLFollowCamMgr::cleanupClass(); - //LLVolumeMgr::cleanupClass(); + SUBSYSTEM_CLEANUP(LLFollowCamMgr); + //SUBSYSTEM_CLEANUP(LLVolumeMgr); LLPrimitive::cleanupVolumeManager(); - LLWorldMapView::cleanupClass(); - LLFolderViewItem::cleanupClass(); - LLUI::cleanupClass(); + SUBSYSTEM_CLEANUP(LLWorldMapView); + SUBSYSTEM_CLEANUP(LLFolderViewItem); + SUBSYSTEM_CLEANUP(LLUI); // // Shut down the VFS's AFTER the decode manager cleans up (since it cleans up vfiles). @@ -1916,7 +1917,7 @@ bool LLAppViewer::cleanup() // LL_INFOS() << "Cleaning up VFS" << LL_ENDL; - LLVFile::cleanupClass(); + SUBSYSTEM_CLEANUP(LLVFile); LL_INFOS() << "Saving Data" << LL_ENDL; @@ -2020,7 +2021,7 @@ bool LLAppViewer::cleanup() // *NOTE:Mani - The following call is not thread safe. LL_CHECK_MEMORY - LLCurl::cleanupClass(); + SUBSYSTEM_CLEANUP(LLCurl); LL_CHECK_MEMORY // Non-LLCurl libcurl library @@ -2029,9 +2030,9 @@ bool LLAppViewer::cleanup() // NOTE The following call is not thread safe. ll_cleanup_ares(); - LLFilePickerThread::cleanupClass(); + SUBSYSTEM_CLEANUP(LLFilePickerThread); - //MUST happen AFTER LLCurl::cleanupClass + //MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl) delete sTextureCache; sTextureCache = NULL; delete sTextureFetch; @@ -2060,17 +2061,17 @@ bool LLAppViewer::cleanup() LL_INFOS() << "Cleaning up Media and Textures" << LL_ENDL; //Note: - //LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown() + //SUBSYSTEM_CLEANUP(LLViewerMedia) has to be put before gTextureList.shutdown() //because some new image might be generated during cleaning up media. --bao - LLViewerMedia::cleanupClass(); - LLViewerParcelMedia::cleanupClass(); + SUBSYSTEM_CLEANUP(LLViewerMedia); + SUBSYSTEM_CLEANUP(LLViewerParcelMedia); gTextureList.shutdown(); // shutdown again in case a callback added something LLUIImageList::getInstance()->cleanUp(); // This should eventually be done in LLAppViewer - LLImage::cleanupClass(); - LLVFSThread::cleanupClass(); - LLLFSThread::cleanupClass(); + SUBSYSTEM_CLEANUP(LLImage); + SUBSYSTEM_CLEANUP(LLVFSThread); + SUBSYSTEM_CLEANUP(LLLFSThread); #ifndef LL_RELEASE_FOR_DOWNLOAD LL_INFOS() << "Auditing VFS" << LL_ENDL; @@ -2113,9 +2114,9 @@ bool LLAppViewer::cleanup() LL_INFOS() << "File launched." << LL_ENDL; } LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL; - LLProxy::cleanupClass(); + SUBSYSTEM_CLEANUP(LLProxy); - LLWearableType::cleanupClass(); + SUBSYSTEM_CLEANUP(LLWearableType); LLMainLoopRepeater::instance().stop(); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 42fc300187..3a85468bda 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -194,6 +194,7 @@ #include "llevents.h" #include "llstartuplistener.h" #include "lltoolbarview.h" +#include "llcleanup.h" #if LL_WINDOWS #include "lldxhardware.h" @@ -2826,7 +2827,7 @@ void LLStartUp::initNameCache() void LLStartUp::cleanupNameCache() { - LLAvatarNameCache::cleanupClass(); + SUBSYSTEM_CLEANUP(LLAvatarNameCache); delete gCacheName; gCacheName = NULL; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 3b0adcf7f4..e7c93926d7 100755 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -130,6 +130,7 @@ #include "llpathfindingmanager.h" #include "llstartup.h" #include "boost/unordered_map.hpp" +#include "llcleanup.h" using namespace LLAvatarAppearanceDefines; @@ -8416,7 +8417,7 @@ class LLWorldPostProcess : public view_listener_t void handle_flush_name_caches() { - LLAvatarNameCache::cleanupClass(); + SUBSYSTEM_CLEANUP(LLAvatarNameCache); if (gCacheName) gCacheName->clear(); } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index a2c0a91ea6..f463c620d3 100755 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -102,6 +102,7 @@ #include "llmediaentry.h" #include "llfloaterperms.h" #include "llvocache.h" +#include "llcleanup.h" //#define DEBUG_UPDATE_TYPE @@ -527,11 +528,11 @@ void LLViewerObject::initVOClasses() void LLViewerObject::cleanupVOClasses() { - LLVOGrass::cleanupClass(); - LLVOWater::cleanupClass(); - LLVOTree::cleanupClass(); - LLVOAvatar::cleanupClass(); - LLVOVolume::cleanupClass(); + SUBSYSTEM_CLEANUP(LLVOGrass); + SUBSYSTEM_CLEANUP(LLVOWater); + SUBSYSTEM_CLEANUP(LLVOTree); + SUBSYSTEM_CLEANUP(LLVOAvatar); + SUBSYSTEM_CLEANUP(LLVOVolume); sObjectDataMap.clear(); } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index e317989f04..12ff88c517 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -208,6 +208,7 @@ #include "llwindowlistener.h" #include "llviewerwindowlistener.h" #include "llpaneltopinfobar.h" +#include "llcleanup.h" #if LL_WINDOWS #include // For Unicode conversion methods @@ -2124,7 +2125,7 @@ void LLViewerWindow::shutdownGL() // Shutdown GL cleanly. Order is very important here. //-------------------------------------------------------- LLFontGL::destroyDefaultFonts(); - LLFontManager::cleanupClass(); + SUBSYSTEM_CLEANUP(LLFontManager); stop_glerror(); gSky.cleanup(); @@ -2147,7 +2148,7 @@ void LLViewerWindow::shutdownGL() LLWorldMapView::cleanupTextures(); LLViewerTextureManager::cleanup() ; - LLImageGL::cleanupClass() ; + SUBSYSTEM_CLEANUP(LLImageGL) ; LL_INFOS() << "All textures and llimagegl images are destroyed!" << LL_ENDL ; @@ -2160,7 +2161,7 @@ void LLViewerWindow::shutdownGL() gGL.shutdown(); - LLVertexBuffer::cleanupClass(); + SUBSYSTEM_CLEANUP(LLVertexBuffer); LL_INFOS() << "LLVertexBuffer cleaned." << LL_ENDL ; } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 03712c1065..9c1b78626f 100755 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -115,6 +115,7 @@ #include "llpathfindingpathtool.h" #include "llscenemonitor.h" #include "llprogressview.h" +#include "llcleanup.h" #ifdef _DEBUG // Debug indices is disabled for now for debug performance - djs 4/24/02 @@ -7373,7 +7374,7 @@ void LLPipeline::doResetVertexBuffers(bool forced) } LLVOPartGroup::destroyGL(); - LLVertexBuffer::cleanupClass(); + SUBSYSTEM_CLEANUP(LLVertexBuffer); //delete all name pool caches LLGLNamePool::cleanupPools(); -- cgit v1.3 From 430263746424bd0a7c6647d25d9d1db5eca2e8c0 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 23 May 2015 12:41:47 -0400 Subject: MAINT-5232: Make gMessageSystem an LLPounceable. This will permit other subsystems to use gMessageSystem.callWhenReady() to (e.g.) register callbacks as soon as gMessageSystem is fully initialized. --- indra/llmessage/message.cpp | 7 +++++-- indra/llmessage/message.h | 3 ++- indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp | 3 ++- indra/llmessage/tests/lltrustedmessageservice_test.cpp | 3 ++- indra/llui/tests/llurlentry_stub.cpp | 3 ++- indra/newview/tests/llremoteparcelrequest_test.cpp | 3 ++- indra/test/message_tut.cpp | 2 +- 7 files changed, 16 insertions(+), 8 deletions(-) (limited to 'indra/llui') diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index e9ce94ab3b..3c3683f12a 100755 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -77,6 +77,7 @@ #include "v3math.h" #include "v4math.h" #include "lltransfertargetvfile.h" +#include "llpounceable.h" // Constants //const char* MESSAGE_LOG_FILENAME = "message.log"; @@ -1776,7 +1777,9 @@ std::ostream& operator<<(std::ostream& s, LLMessageSystem &msg) return s; } -LLMessageSystem *gMessageSystem = NULL; +// LLPounceable supports callWhenReady(), to permit clients to queue up (e.g.) +// callback registrations for when gMessageSystem is first assigned +LLPounceable gMessageSystem; // update appropriate ping info void process_complete_ping_check(LLMessageSystem *msgsystem, void** /*user_data*/) @@ -2693,7 +2696,7 @@ void end_messaging_system(bool print_summary) LL_INFOS("Messaging") << str.str().c_str() << LL_ENDL; } - delete gMessageSystem; + delete static_cast(gMessageSystem); gMessageSystem = NULL; } } diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h index 348b09b992..a6fabf2126 100755 --- a/indra/llmessage/message.h +++ b/indra/llmessage/message.h @@ -60,6 +60,7 @@ #include "llmessagesenderinterface.h" #include "llstoredmessage.h" +#include "llpounceable.h" const U32 MESSAGE_MAX_STRINGS_LENGTH = 64; const U32 MESSAGE_NUMBER_OF_HASH_BUCKETS = 8192; @@ -830,7 +831,7 @@ private: // external hook into messaging system -extern LLMessageSystem *gMessageSystem; +extern LLPounceable gMessageSystem; // Must specific overall system version, which is used to determine // if a patch is available in the message template checksum verification. diff --git a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp index 3b04530c1a..e20f61b73f 100755 --- a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp +++ b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp @@ -31,11 +31,12 @@ #include "llhost.h" #include "message.h" #include "llsd.h" +#include "llpounceable.h" #include "llhost.cpp" // Needed for copy operator #include "net.cpp" // Needed by LLHost. -LLMessageSystem * gMessageSystem = NULL; +LLPounceable gMessageSystem; // sensor test doubles bool gClearRecvWasCalled = false; diff --git a/indra/llmessage/tests/lltrustedmessageservice_test.cpp b/indra/llmessage/tests/lltrustedmessageservice_test.cpp index 55748ad27e..41f982a7e2 100755 --- a/indra/llmessage/tests/lltrustedmessageservice_test.cpp +++ b/indra/llmessage/tests/lltrustedmessageservice_test.cpp @@ -33,8 +33,9 @@ #include "message.h" #include "llmessageconfig.h" #include "llhttpnode_stub.cpp" +#include "llpounceable.h" -LLMessageSystem* gMessageSystem = NULL; +LLPounceable gMessageSystem; LLMessageConfig::SenderTrust LLMessageConfig::getSenderTrustedness(const std::string& msg_name) diff --git a/indra/llui/tests/llurlentry_stub.cpp b/indra/llui/tests/llurlentry_stub.cpp index 5d3f9ac327..d28f601009 100755 --- a/indra/llui/tests/llurlentry_stub.cpp +++ b/indra/llui/tests/llurlentry_stub.cpp @@ -31,6 +31,7 @@ #include "llcachename.h" #include "lluuid.h" #include "message.h" +#include "llpounceable.h" #include @@ -167,7 +168,7 @@ char const* const _PREHASH_AgentID = (char *)"AgentID"; LLHost LLHost::invalid(INVALID_PORT,INVALID_HOST_IP_ADDRESS); -LLMessageSystem* gMessageSystem = NULL; +LLPounceable gMessageSystem; // // Stub implementation for LLMessageSystem diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp index c49b0350e9..5e3649fdae 100755 --- a/indra/newview/tests/llremoteparcelrequest_test.cpp +++ b/indra/newview/tests/llremoteparcelrequest_test.cpp @@ -33,6 +33,7 @@ #include "../llagent.h" #include "message.h" #include "llurlentry.h" +#include "llpounceable.h" namespace { const LLUUID TEST_PARCEL_ID("11111111-1111-1111-1111-111111111111"); @@ -61,7 +62,7 @@ void LLMessageSystem::addUUID(char const *,LLUUID const &) { } void LLMessageSystem::addUUIDFast(char const *,LLUUID const &) { } void LLMessageSystem::nextBlockFast(char const *) { } void LLMessageSystem::newMessage(char const *) { } -LLMessageSystem * gMessageSystem; +LLPounceable gMessageSystem; char const* const _PREHASH_AgentID = 0; // never dereferenced during this test char const* const _PREHASH_AgentData = 0; // never dereferenced during this test LLAgent gAgent; diff --git a/indra/test/message_tut.cpp b/indra/test/message_tut.cpp index aa23699de0..b9c025f518 100755 --- a/indra/test/message_tut.cpp +++ b/indra/test/message_tut.cpp @@ -103,7 +103,7 @@ namespace tut ~LLMessageSystemTestData() { // not end_messaging_system() - delete gMessageSystem; + delete static_cast(gMessageSystem); gMessageSystem = NULL; // rm contents of temp dir -- cgit v1.3 From 9f962c03bf9080d67a8ea10aa53289c841fea781 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 27 May 2015 16:41:10 -0400 Subject: MAINT-5232: Extract LLInitClass, LLDestroyClass from llui/llui.h to a new llcommon/llinitdestroyclass.h. This mechanism is so general -- but has so many related moving parts -- that (a) it deserves to be in a header file all its own, instead of conflated with llui.h, and (b) it should be in llcommon where anyone can use it. It has no dependencies whatsoever on llui or anything viewer-specific. In this very changeset we changed one #include "llui.h" whose comment admits that it was only dragged in for LLDestroyClass. --- indra/llcommon/CMakeLists.txt | 1 + indra/llcommon/llinitdestroyclass.h | 134 ++++++++++++++++++++++++++++++++++++ indra/llui/llspellcheck.h | 1 + indra/llui/llui.h | 89 ------------------------ indra/newview/llagentwearables.h | 1 + indra/newview/llfavoritesbar.h | 1 + indra/newview/llhints.h | 1 + indra/newview/llimview.h | 1 + indra/newview/llnavigationbar.h | 1 + indra/newview/llpaneltopinfobar.h | 1 + indra/newview/llsearchhistory.h | 1 + indra/newview/llsyswellwindow.h | 1 + indra/newview/llviewerinventory.h | 2 +- 13 files changed, 145 insertions(+), 90 deletions(-) create mode 100644 indra/llcommon/llinitdestroyclass.h (limited to 'indra/llui') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index d2d507d676..de5aa0fde4 100755 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -162,6 +162,7 @@ set(llcommon_HEADER_FILES llhash.h llheartbeat.h llindexedvector.h + llinitdestroyclass.h llinitparam.h llinstancetracker.h llkeythrottle.h diff --git a/indra/llcommon/llinitdestroyclass.h b/indra/llcommon/llinitdestroyclass.h new file mode 100644 index 0000000000..ca5c3f07de --- /dev/null +++ b/indra/llcommon/llinitdestroyclass.h @@ -0,0 +1,134 @@ +/** + * @file llinitdestroyclass.h + * @author Nat Goodspeed + * @date 2015-05-27 + * @brief LLInitClass / LLDestroyClass mechanism + * + * The LLInitClass template, extracted from llui.h, ensures that control will + * reach a static initClass() method. LLDestroyClass does the same for a + * static destroyClass() method. + * + * The distinguishing characteristics of these templates are: + * + * - All LLInitClass::initClass() methods are triggered by an explicit call + * to LLInitClassList::instance().fireCallbacks(). Presumably this call + * happens sometime after all static objects in the program have been + * initialized. In other words, each LLInitClass::initClass() method + * should be able to make some assumptions about global program state. + * + * - Similarly, LLDestroyClass::destroyClass() methods are triggered by + * LLDestroyClassList::instance().fireCallbacks(). Again, presumably this + * happens at a well-defined moment in the program's shutdown sequence. + * + * - The initClass() calls happen in an unspecified sequence. You may not rely + * on the relative ordering of LLInitClass::initClass() versus another + * LLInitClass::initClass() method. If you need such a guarantee, use + * LLSingleton instead and make the dependency explicit. + * + * - Similarly, LLDestroyClass::destroyClass() may happen either before or + * after LLDestroyClass::destroyClass(). You cannot rely on that order. + * + * $LicenseInfo:firstyear=2015&license=viewerlgpl$ + * Copyright (c) 2015, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLINITDESTROYCLASS_H) +#define LL_LLINITDESTROYCLASS_H + +#include "llerror.h" +#include "llsingleton.h" +#include +#include +#include + +class LLCallbackRegistry +{ +public: + typedef boost::signals2::signal callback_signal_t; + + void registerCallback(const callback_signal_t::slot_type& slot) + { + mCallbacks.connect(slot); + } + + void fireCallbacks() + { + mCallbacks(); + } + +private: + callback_signal_t mCallbacks; +}; + +class LLInitClassList : + public LLCallbackRegistry, + public LLSingleton +{ + friend class LLSingleton; +private: + LLInitClassList() {} +}; + +class LLDestroyClassList : + public LLCallbackRegistry, + public LLSingleton +{ + friend class LLSingleton; +private: + LLDestroyClassList() {} +}; + +template +class LLRegisterWith +{ +public: + LLRegisterWith(boost::function func) + { + T::instance().registerCallback(func); + } + + // this avoids a MSVC bug where non-referenced static members are "optimized" away + // even if their constructors have side effects + S32 reference() + { + S32 dummy; + dummy = 0; + return dummy; + } +}; + +template +class LLInitClass +{ +public: + LLInitClass() { sRegister.reference(); } + + static LLRegisterWith sRegister; +private: + + static void initClass() + { + LL_ERRS() << "No static initClass() method defined for " << typeid(T).name() << LL_ENDL; + } +}; + +template +class LLDestroyClass +{ +public: + LLDestroyClass() { sRegister.reference(); } + + static LLRegisterWith sRegister; +private: + + static void destroyClass() + { + LL_ERRS() << "No static destroyClass() method defined for " << typeid(T).name() << LL_ENDL; + } +}; + +template LLRegisterWith LLInitClass::sRegister(&T::initClass); +template LLRegisterWith LLDestroyClass::sRegister(&T::destroyClass); + +#endif /* ! defined(LL_LLINITDESTROYCLASS_H) */ diff --git a/indra/llui/llspellcheck.h b/indra/llui/llspellcheck.h index 4ab80195ea..5ecc9aa110 100755 --- a/indra/llui/llspellcheck.h +++ b/indra/llui/llspellcheck.h @@ -29,6 +29,7 @@ #include "llsingleton.h" #include "llui.h" +#include "llinitdestroyclass.h" #include class Hunspell; diff --git a/indra/llui/llui.h b/indra/llui/llui.h index c727f75c4f..d7151dbee9 100755 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -344,95 +344,6 @@ private: // Moved LLLocalClipRect to lllocalcliprect.h -class LLCallbackRegistry -{ -public: - typedef boost::signals2::signal callback_signal_t; - - void registerCallback(const callback_signal_t::slot_type& slot) - { - mCallbacks.connect(slot); - } - - void fireCallbacks() - { - mCallbacks(); - } - -private: - callback_signal_t mCallbacks; -}; - -class LLInitClassList : - public LLCallbackRegistry, - public LLSingleton -{ - friend class LLSingleton; -private: - LLInitClassList() {} -}; - -class LLDestroyClassList : - public LLCallbackRegistry, - public LLSingleton -{ - friend class LLSingleton; -private: - LLDestroyClassList() {} -}; - -template -class LLRegisterWith -{ -public: - LLRegisterWith(boost::function func) - { - T::instance().registerCallback(func); - } - - // this avoids a MSVC bug where non-referenced static members are "optimized" away - // even if their constructors have side effects - S32 reference() - { - S32 dummy; - dummy = 0; - return dummy; - } -}; - -template -class LLInitClass -{ -public: - LLInitClass() { sRegister.reference(); } - - static LLRegisterWith sRegister; -private: - - static void initClass() - { - LL_ERRS() << "No static initClass() method defined for " << typeid(T).name() << LL_ENDL; - } -}; - -template -class LLDestroyClass -{ -public: - LLDestroyClass() { sRegister.reference(); } - - static LLRegisterWith sRegister; -private: - - static void destroyClass() - { - LL_ERRS() << "No static destroyClass() method defined for " << typeid(T).name() << LL_ENDL; - } -}; - -template LLRegisterWith LLInitClass::sRegister(&T::initClass); -template LLRegisterWith LLDestroyClass::sRegister(&T::destroyClass); - // useful parameter blocks struct TimeIntervalParam : public LLInitParam::ChoiceBlock { diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 1004482020..7dc23c6402 100755 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -38,6 +38,7 @@ #include "llviewerinventory.h" #include "llavatarappearancedefines.h" #include "llwearabledata.h" +#include "llinitdestroyclass.h" class LLInventoryItem; class LLVOAvatarSelf; diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index a370724947..574617fa63 100755 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -34,6 +34,7 @@ #include "llinventoryobserver.h" #include "llinventorymodel.h" #include "llviewerinventory.h" +#include "llinitdestroyclass.h" class LLMenuItemCallGL; class LLToggleableMenu; diff --git a/indra/newview/llhints.h b/indra/newview/llhints.h index ebffe561b9..dd6195a9ce 100755 --- a/indra/newview/llhints.h +++ b/indra/newview/llhints.h @@ -29,6 +29,7 @@ #include "llpanel.h" #include "llnotifications.h" +#include "llinitdestroyclass.h" class LLHints : public LLInitClass diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index f92eff4845..79be6fd9d3 100755 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -33,6 +33,7 @@ #include "lllogchat.h" #include "llvoicechannel.h" +#include "llinitdestroyclass.h" class LLAvatarName; class LLFriendObserver; diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h index 7878bab24e..de12a39547 100755 --- a/indra/newview/llnavigationbar.h +++ b/indra/newview/llnavigationbar.h @@ -29,6 +29,7 @@ #include "llpanel.h" #include "llbutton.h" +#include "llinitdestroyclass.h" class LLLocationInputCtrl; class LLMenuGL; diff --git a/indra/newview/llpaneltopinfobar.h b/indra/newview/llpaneltopinfobar.h index f37bd9c048..274d70c6f9 100755 --- a/indra/newview/llpaneltopinfobar.h +++ b/indra/newview/llpaneltopinfobar.h @@ -28,6 +28,7 @@ #define LLPANELTOPINFOBAR_H_ #include "llpanel.h" +#include "llinitdestroyclass.h" class LLButton; class LLTextBox; diff --git a/indra/newview/llsearchhistory.h b/indra/newview/llsearchhistory.h index 3309a8fcac..ade81675c2 100755 --- a/indra/newview/llsearchhistory.h +++ b/indra/newview/llsearchhistory.h @@ -28,6 +28,7 @@ #define LL_LLSEARCHHISTORY_H #include "llsingleton.h" +#include "llinitdestroyclass.h" #include "llui.h" /** diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 71b41476f5..cff3711bb9 100755 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -32,6 +32,7 @@ #include "llscreenchannel.h" #include "llsyswellitem.h" #include "lltransientdockablefloater.h" +#include "llinitdestroyclass.h" class LLAvatarName; class LLChiclet; diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index ca92565600..78b61d4fbc 100755 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -30,7 +30,7 @@ #include "llinventory.h" #include "llframetimer.h" #include "llwearable.h" -#include "llui.h" //for LLDestroyClass +#include "llinitdestroyclass.h" //for LLDestroyClass #include // boost::signals2::trackable -- cgit v1.3