gecko-dev/xpcom/glue/nsCategoryCache.h
Nathan Froyd 150bcb573b Bug 1278925 - micro-optimize nsCOMArray appending with already_AddRefed AppendElement; r=erahm
In all of the places touched by this patch, the smart pointer we're
appending is about to become unused, so simply .forget()'ing its
reference into the appropriate nsCOMArray works just fine.
2016-06-20 18:38:10 -04:00

96 lines
2.3 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsCategoryCache_h_
#define nsCategoryCache_h_
#include "mozilla/Attributes.h"
#include "nsICategoryManager.h"
#include "nsIObserver.h"
#include "nsISimpleEnumerator.h"
#include "nsISupportsPrimitives.h"
#include "nsServiceManagerUtils.h"
#include "nsAutoPtr.h"
#include "nsCOMArray.h"
#include "nsInterfaceHashtable.h"
#include "nsXPCOM.h"
class nsCategoryObserver final : public nsIObserver
{
~nsCategoryObserver();
public:
explicit nsCategoryObserver(const char* aCategory);
void ListenerDied();
nsInterfaceHashtable<nsCStringHashKey, nsISupports>& GetHash()
{
return mHash;
}
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
private:
void RemoveObservers();
nsInterfaceHashtable<nsCStringHashKey, nsISupports> mHash;
nsCString mCategory;
bool mObserversRemoved;
};
/**
* This is a helper class that caches services that are registered in a certain
* category. The intended usage is that a service stores a variable of type
* nsCategoryCache<nsIFoo> in a member variable, where nsIFoo is the interface
* that these services should implement. The constructor of this class should
* then get the name of the category.
*/
template<class T>
class nsCategoryCache final
{
public:
explicit nsCategoryCache(const char* aCategory)
: mCategoryName(aCategory)
{
}
~nsCategoryCache()
{
if (mObserver) {
mObserver->ListenerDied();
}
}
void GetEntries(nsCOMArray<T>& aResult)
{
// Lazy initialization, so that services in this category can't
// cause reentrant getService (bug 386376)
if (!mObserver) {
mObserver = new nsCategoryObserver(mCategoryName.get());
}
for (auto iter = mObserver->GetHash().Iter(); !iter.Done(); iter.Next()) {
nsISupports* entry = iter.UserData();
nsCOMPtr<T> service = do_QueryInterface(entry);
if (service) {
aResult.AppendElement(service.forget());
}
}
}
private:
// Not to be implemented
nsCategoryCache(const nsCategoryCache<T>&);
nsCString mCategoryName;
RefPtr<nsCategoryObserver> mObserver;
};
#endif