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 : #include "nsObserverList.h"
8 :
9 : #include "nsAutoPtr.h"
10 : #include "nsCOMArray.h"
11 : #include "nsISimpleEnumerator.h"
12 : #include "xpcpublic.h"
13 :
14 : nsresult
15 1085 : nsObserverList::AddObserver(nsIObserver* anObserver, bool ownsWeak)
16 : {
17 1085 : NS_ASSERTION(anObserver, "Null input");
18 :
19 1085 : if (!ownsWeak) {
20 781 : ObserverRef* o = mObservers.AppendElement(anObserver);
21 781 : if (!o) {
22 0 : return NS_ERROR_OUT_OF_MEMORY;
23 : }
24 :
25 781 : return NS_OK;
26 : }
27 :
28 608 : nsCOMPtr<nsIWeakReference> weak = do_GetWeakReference(anObserver);
29 304 : if (!weak) {
30 9 : return NS_NOINTERFACE;
31 : }
32 :
33 295 : ObserverRef* o = mObservers.AppendElement(weak);
34 295 : if (!o) {
35 0 : return NS_ERROR_OUT_OF_MEMORY;
36 : }
37 :
38 295 : return NS_OK;
39 : }
40 :
41 : nsresult
42 120 : nsObserverList::RemoveObserver(nsIObserver* anObserver)
43 : {
44 120 : NS_ASSERTION(anObserver, "Null input");
45 :
46 120 : if (mObservers.RemoveElement(static_cast<nsISupports*>(anObserver))) {
47 46 : return NS_OK;
48 : }
49 :
50 148 : nsCOMPtr<nsIWeakReference> observerRef = do_GetWeakReference(anObserver);
51 74 : if (!observerRef) {
52 67 : return NS_ERROR_FAILURE;
53 : }
54 :
55 7 : if (!mObservers.RemoveElement(observerRef)) {
56 0 : return NS_ERROR_FAILURE;
57 : }
58 :
59 7 : return NS_OK;
60 : }
61 :
62 : void
63 0 : nsObserverList::GetObserverList(nsISimpleEnumerator** anEnumerator)
64 : {
65 0 : RefPtr<nsObserverEnumerator> e(new nsObserverEnumerator(this));
66 0 : e.forget(anEnumerator);
67 0 : }
68 :
69 : void
70 208 : nsObserverList::FillObserverArray(nsCOMArray<nsIObserver>& aArray)
71 : {
72 208 : aArray.SetCapacity(mObservers.Length());
73 :
74 416 : nsTArray<ObserverRef> observers(mObservers);
75 :
76 462 : for (int32_t i = observers.Length() - 1; i >= 0; --i) {
77 254 : if (observers[i].isWeakRef) {
78 58 : nsCOMPtr<nsIObserver> o(do_QueryReferent(observers[i].asWeak()));
79 29 : if (o) {
80 29 : aArray.AppendObject(o);
81 : } else {
82 : // the object has gone away, remove the weakref
83 0 : mObservers.RemoveElement(observers[i].asWeak());
84 : }
85 : } else {
86 225 : aArray.AppendObject(observers[i].asObserver());
87 : }
88 : }
89 208 : }
90 :
91 : void
92 0 : nsObserverList::AppendStrongObservers(nsCOMArray<nsIObserver>& aArray)
93 : {
94 0 : aArray.SetCapacity(aArray.Length() + mObservers.Length());
95 :
96 0 : for (int32_t i = mObservers.Length() - 1; i >= 0; --i) {
97 0 : if (!mObservers[i].isWeakRef) {
98 0 : aArray.AppendObject(mObservers[i].asObserver());
99 : }
100 : }
101 0 : }
102 :
103 : void
104 208 : nsObserverList::NotifyObservers(nsISupports* aSubject,
105 : const char* aTopic,
106 : const char16_t* someData)
107 : {
108 416 : nsCOMArray<nsIObserver> observers;
109 208 : FillObserverArray(observers);
110 :
111 462 : for (int32_t i = 0; i < observers.Count(); ++i) {
112 254 : observers[i]->Observe(aSubject, aTopic, someData);
113 : }
114 208 : }
115 :
116 0 : NS_IMPL_ISUPPORTS(nsObserverEnumerator, nsISimpleEnumerator)
117 :
118 0 : nsObserverEnumerator::nsObserverEnumerator(nsObserverList* aObserverList)
119 0 : : mIndex(0)
120 : {
121 0 : aObserverList->FillObserverArray(mObservers);
122 0 : }
123 :
124 : NS_IMETHODIMP
125 0 : nsObserverEnumerator::HasMoreElements(bool* aResult)
126 : {
127 0 : *aResult = (mIndex < mObservers.Count());
128 0 : return NS_OK;
129 : }
130 :
131 : NS_IMETHODIMP
132 0 : nsObserverEnumerator::GetNext(nsISupports** aResult)
133 : {
134 0 : if (mIndex == mObservers.Count()) {
135 0 : NS_ERROR("Enumerating after HasMoreElements returned false.");
136 0 : return NS_ERROR_UNEXPECTED;
137 : }
138 :
139 0 : NS_ADDREF(*aResult = mObservers[mIndex]);
140 0 : ++mIndex;
141 0 : return NS_OK;
142 : }
|