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 nsObserverList_h___
8 #define nsObserverList_h___
9 
10 #include "nsISupports.h"
11 #include "nsTArray.h"
12 #include "nsCOMPtr.h"
13 #include "nsCOMArray.h"
14 #include "nsIObserver.h"
15 #include "nsIWeakReference.h"
16 #include "nsHashKeys.h"
17 #include "nsISimpleEnumerator.h"
18 #include "mozilla/Attributes.h"
19 
20 struct ObserverRef
21 {
ObserverRefObserverRef22   ObserverRef(const ObserverRef& aO) : isWeakRef(aO.isWeakRef), ref(aO.ref) {}
ObserverRefObserverRef23   explicit ObserverRef(nsIObserver* aObserver) : isWeakRef(false), ref(aObserver) {}
ObserverRefObserverRef24   explicit ObserverRef(nsIWeakReference* aWeak) : isWeakRef(true), ref(aWeak) {}
25 
26   bool isWeakRef;
27   nsCOMPtr<nsISupports> ref;
28 
asObserverObserverRef29   nsIObserver* asObserver()
30   {
31     NS_ASSERTION(!isWeakRef, "Isn't a strong ref.");
32     return static_cast<nsIObserver*>((nsISupports*)ref);
33   }
34 
asWeakObserverRef35   nsIWeakReference* asWeak()
36   {
37     NS_ASSERTION(isWeakRef, "Isn't a weak ref.");
38     return static_cast<nsIWeakReference*>((nsISupports*)ref);
39   }
40 
41   bool operator==(nsISupports* aRhs) const { return ref == aRhs; }
42 };
43 
44 class nsObserverList : public nsCharPtrHashKey
45 {
46   friend class nsObserverService;
47 
48 public:
nsObserverList(const char * aKey)49   explicit nsObserverList(const char* aKey) : nsCharPtrHashKey(aKey)
50   {
51     MOZ_COUNT_CTOR(nsObserverList);
52   }
53 
~nsObserverList()54   ~nsObserverList()
55   {
56     MOZ_COUNT_DTOR(nsObserverList);
57   }
58 
59   MOZ_MUST_USE nsresult AddObserver(nsIObserver* aObserver, bool aOwnsWeak);
60   MOZ_MUST_USE nsresult RemoveObserver(nsIObserver* aObserver);
61 
62   void NotifyObservers(nsISupports* aSubject,
63                        const char* aTopic,
64                        const char16_t* aSomeData);
65   void GetObserverList(nsISimpleEnumerator** aEnumerator);
66 
67   // Fill an array with the observers of this category.
68   // The array is filled in last-added-first order.
69   void FillObserverArray(nsCOMArray<nsIObserver>& aArray);
70 
71   // Like FillObserverArray(), but only for strongly held observers.
72   void AppendStrongObservers(nsCOMArray<nsIObserver>& aArray);
73 
74 private:
75   nsTArray<ObserverRef> mObservers;
76 };
77 
78 class nsObserverEnumerator final : public nsISimpleEnumerator
79 {
80 public:
81   NS_DECL_ISUPPORTS
82   NS_DECL_NSISIMPLEENUMERATOR
83 
84   explicit nsObserverEnumerator(nsObserverList* aObserverList);
85 
86 private:
~nsObserverEnumerator()87   ~nsObserverEnumerator() {}
88 
89   int32_t mIndex; // Counts up from 0
90   nsCOMArray<nsIObserver> mObservers;
91 };
92 
93 #endif /* nsObserverList_h___ */
94