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 : // nsWeakReference.cpp
8 :
9 : #include "mozilla/Attributes.h"
10 :
11 : #include "nsWeakReference.h"
12 : #include "nsCOMPtr.h"
13 : #include "nsDebug.h"
14 :
15 : #ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
16 :
17 : #define MOZ_WEAKREF_DECL_OWNINGTHREAD nsAutoOwningThread _mWeakRefOwningThread;
18 : #define MOZ_WEAKREF_ASSERT_OWNINGTHREAD \
19 : _mWeakRefOwningThread.AssertOwnership("nsWeakReference not thread-safe")
20 : #define MOZ_WEAKREF_ASSERT_OWNINGTHREAD_DELEGATED(that) \
21 : (that)->_mWeakRefOwningThread.AssertOwnership("nsWeakReference not thread-safe")
22 :
23 : #else
24 :
25 : #define MOZ_WEAKREF_DECL_OWNINGTHREAD
26 : #define MOZ_WEAKREF_ASSERT_OWNINGTHREAD do { } while (false)
27 : #define MOZ_WEAKREF_ASSERT_OWNINGTHREAD_DELEGATED(that) do { } while (false)
28 :
29 : #endif
30 :
31 : class nsWeakReference final : public nsIWeakReference
32 : {
33 : public:
34 : // nsISupports...
35 : NS_DECL_ISUPPORTS
36 :
37 : // nsIWeakReference...
38 : NS_DECL_NSIWEAKREFERENCE
39 : size_t SizeOfOnlyThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
40 31 : bool IsAlive() const override { return mReferent != nullptr; }
41 :
42 : private:
43 : MOZ_WEAKREF_DECL_OWNINGTHREAD
44 :
45 : friend class nsSupportsWeakReference;
46 :
47 379 : explicit nsWeakReference(nsSupportsWeakReference* aReferent)
48 379 : : mReferent(aReferent)
49 : // ...I can only be constructed by an |nsSupportsWeakReference|
50 : {
51 379 : }
52 :
53 30 : ~nsWeakReference()
54 : // ...I will only be destroyed by calling |delete| myself.
55 60 : {
56 30 : MOZ_WEAKREF_ASSERT_OWNINGTHREAD;
57 30 : if (mReferent) {
58 30 : mReferent->NoticeProxyDestruction();
59 : }
60 30 : }
61 :
62 : void
63 0 : NoticeReferentDestruction()
64 : // ...called (only) by an |nsSupportsWeakReference| from _its_ dtor.
65 : {
66 0 : MOZ_WEAKREF_ASSERT_OWNINGTHREAD;
67 0 : mReferent = nullptr;
68 0 : }
69 :
70 : nsSupportsWeakReference* MOZ_NON_OWNING_REF mReferent;
71 : };
72 :
73 : nsresult
74 6443 : nsQueryReferent::operator()(const nsIID& aIID, void** aAnswer) const
75 : {
76 : nsresult status;
77 6443 : if (mWeakPtr) {
78 4953 : if (NS_FAILED(status = mWeakPtr->QueryReferent(aIID, aAnswer))) {
79 88 : *aAnswer = 0;
80 : }
81 : } else {
82 1490 : status = NS_ERROR_NULL_POINTER;
83 : }
84 :
85 6443 : if (mErrorPtr) {
86 11 : *mErrorPtr = status;
87 : }
88 6443 : return status;
89 : }
90 :
91 : nsIWeakReference* // or else |already_AddRefed<nsIWeakReference>|
92 2230 : NS_GetWeakReference(nsISupports* aInstancePtr, nsresult* aErrorPtr)
93 : {
94 : nsresult status;
95 :
96 2230 : nsIWeakReference* result = nullptr;
97 :
98 2230 : if (aInstancePtr) {
99 : nsCOMPtr<nsISupportsWeakReference> factoryPtr =
100 2186 : do_QueryInterface(aInstancePtr, &status);
101 1093 : if (factoryPtr) {
102 1017 : status = factoryPtr->GetWeakReference(&result);
103 : }
104 : // else, |status| has already been set by |do_QueryInterface|
105 : } else {
106 1137 : status = NS_ERROR_NULL_POINTER;
107 : }
108 :
109 2230 : if (aErrorPtr) {
110 6 : *aErrorPtr = status;
111 : }
112 2230 : return result;
113 : }
114 :
115 : nsresult
116 890 : nsSupportsWeakReference::GetWeakReference(nsIWeakReference** aInstancePtr)
117 : {
118 890 : if (!aInstancePtr) {
119 0 : return NS_ERROR_NULL_POINTER;
120 : }
121 :
122 890 : if (!mProxy) {
123 379 : mProxy = new nsWeakReference(this);
124 : } else {
125 511 : MOZ_WEAKREF_ASSERT_OWNINGTHREAD_DELEGATED(mProxy);
126 : }
127 890 : *aInstancePtr = mProxy;
128 :
129 : nsresult status;
130 890 : if (!*aInstancePtr) {
131 0 : status = NS_ERROR_OUT_OF_MEMORY;
132 : } else {
133 890 : NS_ADDREF(*aInstancePtr);
134 890 : status = NS_OK;
135 : }
136 :
137 890 : return status;
138 : }
139 :
140 4798 : NS_IMPL_ISUPPORTS(nsWeakReference, nsIWeakReference)
141 :
142 : NS_IMETHODIMP
143 14816 : nsWeakReference::QueryReferent(const nsIID& aIID, void** aInstancePtr)
144 : {
145 14816 : MOZ_WEAKREF_ASSERT_OWNINGTHREAD;
146 :
147 14816 : return mReferent ? mReferent->QueryInterface(aIID, aInstancePtr) :
148 14816 : NS_ERROR_NULL_POINTER;
149 : }
150 :
151 : size_t
152 42 : nsWeakReference::SizeOfOnlyThis(mozilla::MallocSizeOf aMallocSizeOf) const
153 : {
154 42 : return aMallocSizeOf(this);
155 : }
156 :
157 : void
158 401 : nsSupportsWeakReference::ClearWeakReferences()
159 : {
160 401 : if (mProxy) {
161 0 : mProxy->NoticeReferentDestruction();
162 0 : mProxy = nullptr;
163 : }
164 410 : }
165 :
|