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 #include "nsObserverList.h"
9 #include "mozilla/ResultExtensions.h"
10 #include "mozilla/Try.h"
11 #include "nsCOMArray.h"
12 #include "xpcpublic.h"
14 nsresult
nsObserverList::AddObserver(nsIObserver
* anObserver
, bool ownsWeak
) {
15 NS_ASSERTION(anObserver
, "Null input");
17 MOZ_TRY(mObservers
.AppendWeakElement(anObserver
, ownsWeak
));
21 nsresult
nsObserverList::RemoveObserver(nsIObserver
* anObserver
) {
22 NS_ASSERTION(anObserver
, "Null input");
24 MOZ_TRY(mObservers
.RemoveWeakElement(anObserver
));
28 void nsObserverList::GetObserverList(nsISimpleEnumerator
** anEnumerator
) {
29 RefPtr
<nsObserverEnumerator
> e(new nsObserverEnumerator(this));
30 e
.forget(anEnumerator
);
33 nsCOMArray
<nsIObserver
> nsObserverList::ReverseCloneObserverArray() {
34 nsCOMArray
<nsIObserver
> array
;
35 array
.SetCapacity(mObservers
.Length());
37 // XXX This could also use RemoveElementsBy if we lifted the promise to fill
38 // aArray in reverse order. Although there shouldn't be anyone explicitly
39 // relying on the order, changing this might cause subtle problems, so we
40 // better leave it as it is.
42 for (int32_t i
= mObservers
.Length() - 1; i
>= 0; --i
) {
43 nsCOMPtr
<nsIObserver
> observer
= mObservers
[i
].GetValue();
45 array
.AppendElement(observer
.forget());
47 // the object has gone away, remove the weakref
48 mObservers
.RemoveElementAt(i
);
55 void nsObserverList::AppendStrongObservers(nsCOMArray
<nsIObserver
>& aArray
) {
56 aArray
.SetCapacity(aArray
.Length() + mObservers
.Length());
58 for (int32_t i
= mObservers
.Length() - 1; i
>= 0; --i
) {
59 if (!mObservers
[i
].IsWeak()) {
60 nsCOMPtr
<nsIObserver
> observer
= mObservers
[i
].GetValue();
61 aArray
.AppendObject(observer
);
66 void nsObserverList::NotifyObservers(nsISupports
* aSubject
, const char* aTopic
,
67 const char16_t
* someData
) {
68 const nsCOMArray
<nsIObserver
> observers
= ReverseCloneObserverArray();
70 for (int32_t i
= 0; i
< observers
.Count(); ++i
) {
71 observers
[i
]->Observe(aSubject
, aTopic
, someData
);
75 nsObserverEnumerator::nsObserverEnumerator(nsObserverList
* aObserverList
)
76 : mIndex(0), mObservers(aObserverList
->ReverseCloneObserverArray()) {}
79 nsObserverEnumerator::HasMoreElements(bool* aResult
) {
80 *aResult
= (mIndex
< mObservers
.Count());
85 nsObserverEnumerator::GetNext(nsISupports
** aResult
) {
86 if (mIndex
== mObservers
.Count()) {
87 return NS_ERROR_FAILURE
;
90 NS_ADDREF(*aResult
= mObservers
[mIndex
]);