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/. */
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
) {
18 #if defined(RELEASE_OR_BETA)
19 flags
|= CRITICAL_SECTION_NO_DEBUG_INFO
;
21 InitializeCriticalSectionEx(&aCS
, 4000, flags
);
29 SharedRef::SharedRef(WeakReferenceSupport
* aSupport
) : mSupport(aSupport
) {
33 SharedRef::~SharedRef() { ::DeleteCriticalSection(&mCS
); }
35 void SharedRef::Lock() { ::EnterCriticalSection(&mCS
); }
37 void SharedRef::Unlock() { ::LeaveCriticalSection(&mCS
); }
40 SharedRef::ToStrongRef(IWeakReferenceSource
** aOutStrongReference
) {
41 RefPtr
<IWeakReferenceSource
> strongRef
;
44 AutoCriticalSection
lock(&mCS
);
51 strongRef
.forget(aOutStrongReference
);
56 SharedRef::Resolve(REFIID aIid
, void** aOutStrongReference
) {
57 RefPtr
<WeakReferenceSupport
> strongRef
;
60 AutoCriticalSection
lock(&mCS
);
67 return strongRef
->QueryInterface(aIid
, aOutStrongReference
);
70 void SharedRef::Clear() {
71 AutoCriticalSection
lock(&mCS
);
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);
86 WeakReferenceSupport::QueryInterface(REFIID riid
, void** ppv
) {
87 RefPtr
<IUnknown
> punk
;
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);
99 HRESULT hr
= WeakRefQueryInterface(riid
, getter_AddRefs(punk
));
106 return E_NOINTERFACE
;
113 WeakReferenceSupport::StabilizeRefCount::StabilizeRefCount(
114 WeakReferenceSupport
& aObject
)
116 SharedRefAutoLock
lock(*mObject
.mSharedRef
);
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
);
130 WeakReferenceSupport::AddRef() {
131 SharedRefAutoLock
lock(*mSharedRef
);
132 ULONG result
= ++mRefCnt
;
133 NS_LOG_ADDREF(this, result
, "mscom::WeakReferenceSupport", sizeof(*this));
138 WeakReferenceSupport::Release() {
141 SharedRefAutoLock
lock(*mSharedRef
);
142 newRefCnt
= --mRefCnt
;
143 if (newRefCnt
== 0) {
147 NS_LOG_RELEASE(this, newRefCnt
, "mscom::WeakReferenceSupport");
148 if (newRefCnt
== 0) {
149 if (mFlags
!= Flags::eDestroyOnMainThread
|| NS_IsMainThread()) {
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());
163 WeakReferenceSupport::GetWeakReference(IWeakReference
** aOutWeakRef
) {
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
);
178 WeakRef::QueryInterface(REFIID riid
, void** ppv
) {
179 IUnknown
* punk
= nullptr;
184 if (riid
== IID_IUnknown
|| riid
== IID_IWeakReference
) {
185 punk
= static_cast<IUnknown
*>(this);
190 return E_NOINTERFACE
;
199 ULONG result
= ++mRefCnt
;
200 NS_LOG_ADDREF(this, result
, "mscom::WeakRef", sizeof(*this));
206 ULONG newRefCnt
= --mRefCnt
;
207 NS_LOG_RELEASE(this, newRefCnt
, "mscom::WeakRef");
208 if (newRefCnt
== 0) {
215 WeakRef::ToStrongRef(IWeakReferenceSource
** aOutStrongReference
) {
216 return mSharedRef
->ToStrongRef(aOutStrongReference
);
220 WeakRef::Resolve(REFIID aIid
, void** aOutStrongReference
) {
221 return mSharedRef
->Resolve(aIid
, aOutStrongReference
);
225 } // namespace mozilla