nsCategoryCache.h 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef nsCategoryCache_h_
  6. #define nsCategoryCache_h_
  7. #include "mozilla/Attributes.h"
  8. #include "nsICategoryManager.h"
  9. #include "nsIObserver.h"
  10. #include "nsISimpleEnumerator.h"
  11. #include "nsISupportsPrimitives.h"
  12. #include "nsServiceManagerUtils.h"
  13. #include "nsAutoPtr.h"
  14. #include "nsCOMArray.h"
  15. #include "nsInterfaceHashtable.h"
  16. #include "nsXPCOM.h"
  17. class nsCategoryObserver final : public nsIObserver
  18. {
  19. ~nsCategoryObserver();
  20. public:
  21. explicit nsCategoryObserver(const char* aCategory);
  22. void ListenerDied();
  23. nsInterfaceHashtable<nsCStringHashKey, nsISupports>& GetHash()
  24. {
  25. return mHash;
  26. }
  27. NS_DECL_ISUPPORTS
  28. NS_DECL_NSIOBSERVER
  29. private:
  30. void RemoveObservers();
  31. nsInterfaceHashtable<nsCStringHashKey, nsISupports> mHash;
  32. nsCString mCategory;
  33. bool mObserversRemoved;
  34. };
  35. /**
  36. * This is a helper class that caches services that are registered in a certain
  37. * category. The intended usage is that a service stores a variable of type
  38. * nsCategoryCache<nsIFoo> in a member variable, where nsIFoo is the interface
  39. * that these services should implement. The constructor of this class should
  40. * then get the name of the category.
  41. */
  42. template<class T>
  43. class nsCategoryCache final
  44. {
  45. public:
  46. explicit nsCategoryCache(const char* aCategory)
  47. : mCategoryName(aCategory)
  48. {
  49. }
  50. ~nsCategoryCache()
  51. {
  52. if (mObserver) {
  53. mObserver->ListenerDied();
  54. }
  55. }
  56. void GetEntries(nsCOMArray<T>& aResult)
  57. {
  58. // Lazy initialization, so that services in this category can't
  59. // cause reentrant getService (bug 386376)
  60. if (!mObserver) {
  61. mObserver = new nsCategoryObserver(mCategoryName.get());
  62. }
  63. for (auto iter = mObserver->GetHash().Iter(); !iter.Done(); iter.Next()) {
  64. nsISupports* entry = iter.UserData();
  65. nsCOMPtr<T> service = do_QueryInterface(entry);
  66. if (service) {
  67. aResult.AppendElement(service.forget());
  68. }
  69. }
  70. }
  71. private:
  72. // Not to be implemented
  73. nsCategoryCache(const nsCategoryCache<T>&);
  74. nsCString mCategoryName;
  75. RefPtr<nsCategoryObserver> mObserver;
  76. };
  77. #endif