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: #ifndef nsCategoryCache_h_ michael@0: #define nsCategoryCache_h_ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: michael@0: #include "nsICategoryManager.h" michael@0: #include "nsIObserver.h" michael@0: #include "nsISimpleEnumerator.h" michael@0: #include "nsISupportsPrimitives.h" michael@0: michael@0: #include "nsServiceManagerUtils.h" michael@0: michael@0: #include "nsAutoPtr.h" michael@0: #include "nsCOMArray.h" michael@0: #include "nsInterfaceHashtable.h" michael@0: michael@0: #include "nsXPCOM.h" michael@0: michael@0: class NS_COM_GLUE nsCategoryObserver MOZ_FINAL : public nsIObserver michael@0: { michael@0: public: michael@0: nsCategoryObserver(const char* aCategory); michael@0: ~nsCategoryObserver(); michael@0: michael@0: void ListenerDied(); michael@0: nsInterfaceHashtable& GetHash() michael@0: { michael@0: return mHash; michael@0: } michael@0: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSIOBSERVER michael@0: private: michael@0: void RemoveObservers(); michael@0: michael@0: nsInterfaceHashtable mHash; michael@0: nsCString mCategory; michael@0: bool mObserversRemoved; michael@0: }; michael@0: michael@0: /** michael@0: * This is a helper class that caches services that are registered in a certain michael@0: * category. The intended usage is that a service stores a variable of type michael@0: * nsCategoryCache in a member variable, where nsIFoo is the interface michael@0: * that these services should implement. The constructor of this class should michael@0: * then get the name of the category. michael@0: */ michael@0: template michael@0: class nsCategoryCache MOZ_FINAL michael@0: { michael@0: public: michael@0: explicit nsCategoryCache(const char* aCategory) michael@0: : mCategoryName(aCategory) michael@0: { michael@0: } michael@0: ~nsCategoryCache() { michael@0: if (mObserver) michael@0: mObserver->ListenerDied(); michael@0: } michael@0: michael@0: void GetEntries(nsCOMArray& result) { michael@0: // Lazy initialization, so that services in this category can't michael@0: // cause reentrant getService (bug 386376) michael@0: if (!mObserver) michael@0: mObserver = new nsCategoryObserver(mCategoryName.get()); michael@0: michael@0: mObserver->GetHash().EnumerateRead(EntriesToArray, &result); michael@0: } michael@0: michael@0: private: michael@0: // Not to be implemented michael@0: nsCategoryCache(const nsCategoryCache&); michael@0: michael@0: static PLDHashOperator EntriesToArray(const nsACString& key, michael@0: nsISupports* entry, void* arg) michael@0: { michael@0: nsCOMArray& entries = *static_cast*>(arg); michael@0: michael@0: nsCOMPtr service = do_QueryInterface(entry); michael@0: if (service) { michael@0: entries.AppendObject(service); michael@0: } michael@0: return PL_DHASH_NEXT; michael@0: } michael@0: michael@0: nsCString mCategoryName; michael@0: nsRefPtr mObserver; michael@0: michael@0: }; michael@0: michael@0: #endif