LCOV - code coverage report
Current view: top level - xpcom/components - nsCategoryCache.h (source / functions) Hit Total Coverage
Test: output.info Lines: 40 40 100.0 %
Date: 2017-07-14 16:53:18 Functions: 31 56 55.4 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       6             : 
       7             : #ifndef nsCategoryCache_h_
       8             : #define nsCategoryCache_h_
       9             : 
      10             : #include "mozilla/Attributes.h"
      11             : 
      12             : #include "nsICategoryManager.h"
      13             : #include "nsIObserver.h"
      14             : #include "nsISimpleEnumerator.h"
      15             : #include "nsISupportsPrimitives.h"
      16             : 
      17             : #include "nsServiceManagerUtils.h"
      18             : 
      19             : #include "nsAutoPtr.h"
      20             : #include "nsCOMArray.h"
      21             : #include "nsInterfaceHashtable.h"
      22             : 
      23             : #include "nsXPCOM.h"
      24             : #include "MainThreadUtils.h"
      25             : 
      26           1 : class nsCategoryObserver final : public nsIObserver
      27             : {
      28             :   ~nsCategoryObserver();
      29             : 
      30             : public:
      31             :   explicit nsCategoryObserver(const char* aCategory);
      32             : 
      33             :   void ListenerDied();
      34             :   void SetListener(void(aCallback)(void*), void* aClosure);
      35          34 :   nsInterfaceHashtable<nsCStringHashKey, nsISupports>& GetHash()
      36             :   {
      37          34 :     return mHash;
      38             :   }
      39             : 
      40             :   NS_DECL_ISUPPORTS
      41             :   NS_DECL_NSIOBSERVER
      42             : private:
      43             :   void RemoveObservers();
      44             : 
      45             :   nsInterfaceHashtable<nsCStringHashKey, nsISupports> mHash;
      46             :   nsCString mCategory;
      47             :   void(*mCallback)(void*);
      48             :   void *mClosure;
      49             :   bool mObserversRemoved;
      50             : };
      51             : 
      52             : /**
      53             :  * This is a helper class that caches services that are registered in a certain
      54             :  * category. The intended usage is that a service stores a variable of type
      55             :  * nsCategoryCache<nsIFoo> in a member variable, where nsIFoo is the interface
      56             :  * that these services should implement. The constructor of this class should
      57             :  * then get the name of the category.
      58             :  */
      59             : template<class T>
      60             : class nsCategoryCache final
      61             : {
      62             : public:
      63          16 :   explicit nsCategoryCache(const char* aCategory)
      64          16 :     : mCategoryName(aCategory)
      65             :   {
      66          16 :     MOZ_ASSERT(NS_IsMainThread());
      67          16 :   }
      68           1 :   ~nsCategoryCache()
      69             :   {
      70           1 :     MOZ_ASSERT(NS_IsMainThread());
      71           1 :     if (mObserver) {
      72           1 :       mObserver->ListenerDied();
      73             :     }
      74           1 :   }
      75             : 
      76           9 :   void GetEntries(nsCOMArray<T>& aResult)
      77             :   {
      78           9 :     MOZ_ASSERT(NS_IsMainThread());
      79           9 :     LazyInit();
      80             : 
      81           9 :     AddEntries(aResult);
      82           9 :   }
      83             : 
      84             :   /**
      85             :    * This function returns an nsCOMArray of interface pointers to the cached
      86             :    * category enries for the requested category.  This was added in order to be
      87             :    * used in call sites where the overhead of excessive allocations can be
      88             :    * unacceptable.  See bug 1360971 for an example.
      89             :    */
      90          46 :   const nsCOMArray<T>& GetCachedEntries()
      91             :   {
      92          46 :     MOZ_ASSERT(NS_IsMainThread());
      93          46 :     LazyInit();
      94             : 
      95          46 :     if (mCachedEntries.IsEmpty()) {
      96          25 :       AddEntries(mCachedEntries);
      97             :     }
      98          46 :     return mCachedEntries;
      99             :   }
     100             : 
     101             : private:
     102          55 :   void LazyInit()
     103             :   {
     104             :     // Lazy initialization, so that services in this category can't
     105             :     // cause reentrant getService (bug 386376)
     106          55 :     if (!mObserver) {
     107          18 :       mObserver = new nsCategoryObserver(mCategoryName.get());
     108           9 :       mObserver->SetListener(nsCategoryCache<T>::OnCategoryChanged, this);
     109             :     }
     110          55 :   }
     111             : 
     112          34 :   void AddEntries(nsCOMArray<T>& aResult)
     113             :   {
     114          64 :     for (auto iter = mObserver->GetHash().Iter(); !iter.Done(); iter.Next()) {
     115          30 :       nsISupports* entry = iter.UserData();
     116          60 :       nsCOMPtr<T> service = do_QueryInterface(entry);
     117          30 :       if (service) {
     118          30 :         aResult.AppendElement(service.forget());
     119             :       }
     120             :     }
     121          34 :   }
     122             : 
     123           2 :   static void OnCategoryChanged(void* aClosure)
     124             :   {
     125           2 :     MOZ_ASSERT(NS_IsMainThread());
     126           2 :     auto self = static_cast<nsCategoryCache<T>*>(aClosure);
     127           2 :     self->mCachedEntries.Clear();
     128           2 :   }
     129             : 
     130             : private:
     131             :   // Not to be implemented
     132             :   nsCategoryCache(const nsCategoryCache<T>&);
     133             : 
     134             :   nsCString mCategoryName;
     135             :   RefPtr<nsCategoryObserver> mObserver;
     136             :   nsCOMArray<T> mCachedEntries;
     137             : };
     138             : 
     139             : #endif

Generated by: LCOV version 1.13