michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: michael@0: #ifndef NSCATEGORYMANAGER_H michael@0: #define NSCATEGORYMANAGER_H michael@0: michael@0: #include "prio.h" michael@0: #include "plarena.h" michael@0: #include "nsClassHashtable.h" michael@0: #include "nsICategoryManager.h" michael@0: #include "nsIMemoryReporter.h" michael@0: #include "mozilla/MemoryReporting.h" michael@0: #include "mozilla/Mutex.h" michael@0: #include "mozilla/Attributes.h" michael@0: michael@0: class nsIMemoryReporter; michael@0: michael@0: /* 16d222a6-1dd2-11b2-b693-f38b02c021b2 */ michael@0: #define NS_CATEGORYMANAGER_CID \ michael@0: { 0x16d222a6, 0x1dd2, 0x11b2, \ michael@0: {0xb6, 0x93, 0xf3, 0x8b, 0x02, 0xc0, 0x21, 0xb2} } michael@0: michael@0: /** michael@0: * a "leaf-node", managed by the nsCategoryNode hashtable. michael@0: * michael@0: * we need to keep a "persistent value" (which will be written to the registry) michael@0: * and a non-persistent value (for the current runtime): these are usually michael@0: * the same, except when aPersist==false. The strings are permanently arena- michael@0: * allocated, and will never go away. michael@0: */ michael@0: class CategoryLeaf : public nsDepCharHashKey michael@0: { michael@0: public: michael@0: CategoryLeaf(const char* aKey) michael@0: : nsDepCharHashKey(aKey), michael@0: value(nullptr) { } michael@0: const char* value; michael@0: }; michael@0: michael@0: michael@0: /** michael@0: * CategoryNode keeps a hashtable of its entries. michael@0: * the CategoryNode itself is permanently allocated in michael@0: * the arena. michael@0: */ michael@0: class CategoryNode michael@0: { michael@0: public: michael@0: NS_METHOD GetLeaf(const char* aEntryName, michael@0: char** _retval); michael@0: michael@0: NS_METHOD AddLeaf(const char* aEntryName, michael@0: const char* aValue, michael@0: bool aReplace, michael@0: char** _retval, michael@0: PLArenaPool* aArena); michael@0: michael@0: void DeleteLeaf(const char* aEntryName); michael@0: michael@0: void Clear() { michael@0: mozilla::MutexAutoLock lock(mLock); michael@0: mTable.Clear(); michael@0: } michael@0: michael@0: uint32_t Count() { michael@0: mozilla::MutexAutoLock lock(mLock); michael@0: uint32_t tCount = mTable.Count(); michael@0: return tCount; michael@0: } michael@0: michael@0: NS_METHOD Enumerate(nsISimpleEnumerator** _retval); michael@0: michael@0: // CategoryNode is arena-allocated, with the strings michael@0: static CategoryNode* Create(PLArenaPool* aArena); michael@0: ~CategoryNode(); michael@0: void operator delete(void*) { } michael@0: michael@0: size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf); michael@0: michael@0: private: michael@0: CategoryNode() michael@0: : mLock("CategoryLeaf") michael@0: { } michael@0: michael@0: void* operator new(size_t aSize, PLArenaPool* aArena); michael@0: michael@0: nsTHashtable mTable; michael@0: mozilla::Mutex mLock; michael@0: }; michael@0: michael@0: michael@0: /** michael@0: * The main implementation of nsICategoryManager. michael@0: * michael@0: * This implementation is thread-safe. michael@0: */ michael@0: class nsCategoryManager MOZ_FINAL michael@0: : public nsICategoryManager michael@0: , public nsIMemoryReporter michael@0: { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSICATEGORYMANAGER michael@0: NS_DECL_NSIMEMORYREPORTER michael@0: michael@0: /** michael@0: * Suppress or unsuppress notifications of category changes to the michael@0: * observer service. This is to be used by nsComponentManagerImpl michael@0: * on startup while reading the stored category list. michael@0: */ michael@0: NS_METHOD SuppressNotifications(bool aSuppress); michael@0: michael@0: void AddCategoryEntry(const char* aCategory, michael@0: const char* aKey, michael@0: const char* aValue, michael@0: bool aReplace = true, michael@0: char** aOldValue = nullptr); michael@0: michael@0: static nsresult Create(nsISupports* aOuter, REFNSIID aIID, void** aResult); michael@0: void InitMemoryReporter(); michael@0: michael@0: static nsCategoryManager* GetSingleton(); michael@0: static void Destroy(); michael@0: michael@0: private: michael@0: static nsCategoryManager* gCategoryManager; michael@0: michael@0: nsCategoryManager(); michael@0: ~nsCategoryManager(); michael@0: michael@0: size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf); michael@0: michael@0: CategoryNode* get_category(const char* aName); michael@0: void NotifyObservers(const char* aTopic, michael@0: const char* aCategoryName, // must be a static string michael@0: const char* aEntryName); michael@0: michael@0: PLArenaPool mArena; michael@0: nsClassHashtable mTable; michael@0: mozilla::Mutex mLock; michael@0: bool mSuppressNotifications; michael@0: }; michael@0: michael@0: #endif