Bug 1761357 [wpt PR 33355] - Fix #33204: Move Safari stable runs to Big Sur, a=testonly
[gecko.git] / ipc / mscom / WeakRef.cpp
blobb15c027153e16f34030047a4fdc187d9ad8929d6
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 #define INITGUID
8 #include "mozilla/mscom/WeakRef.h"
10 #include "mozilla/DebugOnly.h"
11 #include "mozilla/Mutex.h"
12 #include "nsThreadUtils.h"
13 #include "nsWindowsHelpers.h"
14 #include "nsProxyRelease.h"
16 static void InitializeCS(CRITICAL_SECTION& aCS) {
17 DWORD flags = 0;
18 #if defined(RELEASE_OR_BETA)
19 flags |= CRITICAL_SECTION_NO_DEBUG_INFO;
20 #endif
21 InitializeCriticalSectionEx(&aCS, 4000, flags);
24 namespace mozilla {
25 namespace mscom {
27 namespace detail {
29 SharedRef::SharedRef(WeakReferenceSupport* aSupport) : mSupport(aSupport) {
30 ::InitializeCS(mCS);
33 SharedRef::~SharedRef() { ::DeleteCriticalSection(&mCS); }
35 void SharedRef::Lock() { ::EnterCriticalSection(&mCS); }
37 void SharedRef::Unlock() { ::LeaveCriticalSection(&mCS); }
39 HRESULT
40 SharedRef::ToStrongRef(IWeakReferenceSource** aOutStrongReference) {
41 RefPtr<IWeakReferenceSource> strongRef;
43 { // Scope for lock
44 AutoCriticalSection lock(&mCS);
45 if (!mSupport) {
46 return E_POINTER;
48 strongRef = mSupport;
51 strongRef.forget(aOutStrongReference);
52 return S_OK;
55 HRESULT
56 SharedRef::Resolve(REFIID aIid, void** aOutStrongReference) {
57 RefPtr<WeakReferenceSupport> strongRef;
59 { // Scope for lock
60 AutoCriticalSection lock(&mCS);
61 if (!mSupport) {
62 return E_POINTER;
64 strongRef = mSupport;
67 return strongRef->QueryInterface(aIid, aOutStrongReference);
70 void SharedRef::Clear() {
71 AutoCriticalSection lock(&mCS);
72 mSupport = nullptr;
75 } // namespace detail
77 typedef mozilla::detail::BaseAutoLock<detail::SharedRef&> SharedRefAutoLock;
78 typedef mozilla::detail::BaseAutoUnlock<detail::SharedRef&> SharedRefAutoUnlock;
80 WeakReferenceSupport::WeakReferenceSupport(Flags aFlags)
81 : mRefCnt(0), mFlags(aFlags) {
82 mSharedRef = new detail::SharedRef(this);
85 HRESULT
86 WeakReferenceSupport::QueryInterface(REFIID riid, void** ppv) {
87 RefPtr<IUnknown> punk;
88 if (!ppv) {
89 return E_INVALIDARG;
91 *ppv = nullptr;
93 // Raise the refcount for stabilization purposes during aggregation
94 StabilizeRefCount stabilize(*this);
96 if (riid == IID_IUnknown || riid == IID_IWeakReferenceSource) {
97 punk = static_cast<IUnknown*>(this);
98 } else {
99 HRESULT hr = WeakRefQueryInterface(riid, getter_AddRefs(punk));
100 if (FAILED(hr)) {
101 return hr;
105 if (!punk) {
106 return E_NOINTERFACE;
109 punk.forget(ppv);
110 return S_OK;
113 WeakReferenceSupport::StabilizeRefCount::StabilizeRefCount(
114 WeakReferenceSupport& aObject)
115 : mObject(aObject) {
116 SharedRefAutoLock lock(*mObject.mSharedRef);
117 ++mObject.mRefCnt;
120 WeakReferenceSupport::StabilizeRefCount::~StabilizeRefCount() {
121 // We directly access these fields instead of calling Release() because we
122 // want to adjust the ref count without the other side effects (such as
123 // deleting this if the count drops back to zero, which may happen during
124 // an initial QI during object creation).
125 SharedRefAutoLock lock(*mObject.mSharedRef);
126 --mObject.mRefCnt;
129 ULONG
130 WeakReferenceSupport::AddRef() {
131 SharedRefAutoLock lock(*mSharedRef);
132 ULONG result = ++mRefCnt;
133 NS_LOG_ADDREF(this, result, "mscom::WeakReferenceSupport", sizeof(*this));
134 return result;
137 ULONG
138 WeakReferenceSupport::Release() {
139 ULONG newRefCnt;
140 { // Scope for lock
141 SharedRefAutoLock lock(*mSharedRef);
142 newRefCnt = --mRefCnt;
143 if (newRefCnt == 0) {
144 mSharedRef->Clear();
147 NS_LOG_RELEASE(this, newRefCnt, "mscom::WeakReferenceSupport");
148 if (newRefCnt == 0) {
149 if (mFlags != Flags::eDestroyOnMainThread || NS_IsMainThread()) {
150 delete this;
151 } else {
152 // We need to delete this object on the main thread, but we aren't on the
153 // main thread right now, so we send a reference to ourselves to the main
154 // thread to be re-released there.
155 RefPtr<WeakReferenceSupport> self = this;
156 NS_ReleaseOnMainThread("WeakReferenceSupport", self.forget());
159 return newRefCnt;
162 HRESULT
163 WeakReferenceSupport::GetWeakReference(IWeakReference** aOutWeakRef) {
164 if (!aOutWeakRef) {
165 return E_INVALIDARG;
168 RefPtr<WeakRef> weakRef = MakeAndAddRef<WeakRef>(mSharedRef);
169 return weakRef->QueryInterface(IID_IWeakReference, (void**)aOutWeakRef);
172 WeakRef::WeakRef(RefPtr<detail::SharedRef>& aSharedRef)
173 : mRefCnt(0), mSharedRef(aSharedRef) {
174 MOZ_ASSERT(aSharedRef);
177 HRESULT
178 WeakRef::QueryInterface(REFIID riid, void** ppv) {
179 IUnknown* punk = nullptr;
180 if (!ppv) {
181 return E_INVALIDARG;
184 if (riid == IID_IUnknown || riid == IID_IWeakReference) {
185 punk = static_cast<IUnknown*>(this);
188 *ppv = punk;
189 if (!punk) {
190 return E_NOINTERFACE;
193 punk->AddRef();
194 return S_OK;
197 ULONG
198 WeakRef::AddRef() {
199 ULONG result = ++mRefCnt;
200 NS_LOG_ADDREF(this, result, "mscom::WeakRef", sizeof(*this));
201 return result;
204 ULONG
205 WeakRef::Release() {
206 ULONG newRefCnt = --mRefCnt;
207 NS_LOG_RELEASE(this, newRefCnt, "mscom::WeakRef");
208 if (newRefCnt == 0) {
209 delete this;
211 return newRefCnt;
214 HRESULT
215 WeakRef::ToStrongRef(IWeakReferenceSource** aOutStrongReference) {
216 return mSharedRef->ToStrongRef(aOutStrongReference);
219 HRESULT
220 WeakRef::Resolve(REFIID aIid, void** aOutStrongReference) {
221 return mSharedRef->Resolve(aIid, aOutStrongReference);
224 } // namespace mscom
225 } // namespace mozilla