1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef NSCATEGORYMANAGER_H 8 #define NSCATEGORYMANAGER_H 9 10 #include "prio.h" 11 #include "nsClassHashtable.h" 12 #include "nsICategoryManager.h" 13 #include "nsIMemoryReporter.h" 14 #include "mozilla/ArenaAllocator.h" 15 #include "mozilla/MemoryReporting.h" 16 #include "mozilla/Mutex.h" 17 #include "mozilla/Attributes.h" 18 19 class nsIMemoryReporter; 20 21 typedef mozilla::ArenaAllocator<1024 * 8, 8> CategoryAllocator; 22 23 /* 16d222a6-1dd2-11b2-b693-f38b02c021b2 */ 24 #define NS_CATEGORYMANAGER_CID \ 25 { \ 26 0x16d222a6, 0x1dd2, 0x11b2, { \ 27 0xb6, 0x93, 0xf3, 0x8b, 0x02, 0xc0, 0x21, 0xb2 \ 28 } \ 29 } 30 31 /** 32 * a "leaf-node", managed by the nsCategoryNode hashtable. 33 * 34 * we need to keep a "persistent value" (which will be written to the registry) 35 * and a non-persistent value (for the current runtime): these are usually 36 * the same, except when aPersist==false. The strings are permanently arena- 37 * allocated, and will never go away. 38 */ 39 class CategoryLeaf : public nsDepCharHashKey { 40 public: CategoryLeaf(const char * aKey)41 explicit CategoryLeaf(const char* aKey) 42 : nsDepCharHashKey(aKey), value(nullptr) {} 43 const char* value; 44 }; 45 46 /** 47 * CategoryNode keeps a hashtable of its entries. 48 * the CategoryNode itself is permanently allocated in 49 * the arena. 50 */ 51 class CategoryNode { 52 public: 53 nsresult GetLeaf(const nsACString& aEntryName, nsACString& aResult); 54 55 nsresult AddLeaf(const nsACString& aEntryName, const nsACString& aValue, 56 bool aReplace, nsACString& aResult, 57 CategoryAllocator* aArena); 58 59 void DeleteLeaf(const nsACString& aEntryName); 60 Clear()61 void Clear() { 62 mozilla::MutexAutoLock lock(mLock); 63 mTable.Clear(); 64 } 65 Count()66 uint32_t Count() { 67 mozilla::MutexAutoLock lock(mLock); 68 uint32_t tCount = mTable.Count(); 69 return tCount; 70 } 71 72 nsresult Enumerate(nsISimpleEnumerator** aResult); 73 74 // CategoryNode is arena-allocated, with the strings 75 static CategoryNode* Create(CategoryAllocator* aArena); 76 ~CategoryNode(); delete(void *)77 void operator delete(void*) {} 78 79 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf); 80 81 private: CategoryNode()82 CategoryNode() : mLock("CategoryLeaf") {} 83 84 void* operator new(size_t aSize, CategoryAllocator* aArena); 85 86 nsTHashtable<CategoryLeaf> mTable; 87 mozilla::Mutex mLock; 88 }; 89 90 /** 91 * The main implementation of nsICategoryManager. 92 * 93 * This implementation is thread-safe. 94 */ 95 class nsCategoryManager final : public nsICategoryManager, 96 public nsIMemoryReporter { 97 public: 98 NS_DECL_ISUPPORTS 99 NS_DECL_NSICATEGORYMANAGER 100 NS_DECL_NSIMEMORYREPORTER 101 102 /** 103 * Suppress or unsuppress notifications of category changes to the 104 * observer service. This is to be used by nsComponentManagerImpl 105 * on startup while reading the stored category list. 106 */ 107 nsresult SuppressNotifications(bool aSuppress); 108 109 void AddCategoryEntry(const nsACString& aCategory, const nsACString& aKey, 110 const nsACString& aValue, bool aReplace, 111 nsACString& aOldValue); 112 113 void AddCategoryEntry(const nsACString& aCategory, const nsACString& aKey, 114 const nsACString& aValue, bool aReplace = true) { 115 nsCString oldValue; 116 return AddCategoryEntry(aCategory, aKey, aValue, aReplace, oldValue); 117 } 118 119 static nsresult Create(nsISupports* aOuter, REFNSIID aIID, void** aResult); 120 void InitMemoryReporter(); 121 122 static nsCategoryManager* GetSingleton(); 123 static void Destroy(); 124 125 private: 126 static nsCategoryManager* gCategoryManager; 127 128 nsCategoryManager(); 129 ~nsCategoryManager(); 130 131 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf); 132 133 CategoryNode* get_category(const nsACString& aName); 134 void NotifyObservers( 135 const char* aTopic, 136 const nsACString& aCategoryName, // must be a static string 137 const nsACString& aEntryName); 138 139 CategoryAllocator mArena; 140 nsClassHashtable<nsDepCharHashKey, CategoryNode> mTable; 141 mozilla::Mutex mLock; 142 bool mSuppressNotifications; 143 }; 144 145 #endif 146