Bug 1876335 - use GRADLE_MAVEN_REPOSITORIES in more places. r=owlish,geckoview-review...
[gecko.git] / xpcom / components / nsCategoryCache.h
blobf2d7ba32a3b25de67978c191ee25483afedf2ef1
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/. */
7 #ifndef nsCategoryCache_h_
8 #define nsCategoryCache_h_
10 #include "mozilla/Attributes.h"
12 #include "nsIObserver.h"
14 #include "nsServiceManagerUtils.h"
16 #include "nsCOMArray.h"
17 #include "nsInterfaceHashtable.h"
19 #include "nsXPCOM.h"
20 #include "MainThreadUtils.h"
22 class nsCategoryObserver final : public nsIObserver {
23 ~nsCategoryObserver();
25 public:
26 explicit nsCategoryObserver(const nsACString& aCategory);
28 void ListenerDied();
29 void SetListener(void(aCallback)(void*), void* aClosure);
30 nsInterfaceHashtable<nsCStringHashKey, nsISupports>& GetHash() {
31 return mHash;
34 NS_DECL_ISUPPORTS
35 NS_DECL_NSIOBSERVER
36 private:
37 void RemoveObservers();
39 nsInterfaceHashtable<nsCStringHashKey, nsISupports> mHash;
40 nsCString mCategory;
41 void (*mCallback)(void*);
42 void* mClosure;
43 bool mObserversRemoved;
46 /**
47 * This is a helper class that caches services that are registered in a certain
48 * category. The intended usage is that a service stores a variable of type
49 * nsCategoryCache<nsIFoo> in a member variable, where nsIFoo is the interface
50 * that these services should implement. The constructor of this class should
51 * then get the name of the category.
53 template <class T>
54 class nsCategoryCache final {
55 public:
56 explicit nsCategoryCache(const char* aCategory) : mCategoryName(aCategory) {
57 MOZ_ASSERT(NS_IsMainThread());
59 ~nsCategoryCache() {
60 MOZ_ASSERT(NS_IsMainThread());
61 if (mObserver) {
62 mObserver->ListenerDied();
66 void GetEntries(nsCOMArray<T>& aResult) {
67 MOZ_ASSERT(NS_IsMainThread());
68 LazyInit();
70 AddEntries(aResult);
73 /**
74 * This function returns an nsCOMArray of interface pointers to the cached
75 * category enries for the requested category. This was added in order to be
76 * used in call sites where the overhead of excessive allocations can be
77 * unacceptable. See bug 1360971 for an example.
79 const nsCOMArray<T>& GetCachedEntries() {
80 MOZ_ASSERT(NS_IsMainThread());
81 LazyInit();
83 if (mCachedEntries.IsEmpty()) {
84 AddEntries(mCachedEntries);
86 return mCachedEntries;
89 private:
90 void LazyInit() {
91 // Lazy initialization, so that services in this category can't
92 // cause reentrant getService (bug 386376)
93 if (!mObserver) {
94 mObserver = new nsCategoryObserver(mCategoryName);
95 mObserver->SetListener(nsCategoryCache<T>::OnCategoryChanged, this);
99 void AddEntries(nsCOMArray<T>& aResult) {
100 for (nsISupports* entry : mObserver->GetHash().Values()) {
101 nsCOMPtr<T> service = do_QueryInterface(entry);
102 if (service) {
103 aResult.AppendElement(service.forget());
108 static void OnCategoryChanged(void* aClosure) {
109 MOZ_ASSERT(NS_IsMainThread());
110 auto self = static_cast<nsCategoryCache<T>*>(aClosure);
111 self->mCachedEntries.Clear();
114 private:
115 // Not to be implemented
116 nsCategoryCache(const nsCategoryCache<T>&);
118 nsCString mCategoryName;
119 RefPtr<nsCategoryObserver> mObserver;
120 nsCOMArray<T> mCachedEntries;
123 #endif