Skip to content

Commit 061e78a

Browse files
committed
Bug 1489317: Part 2 - Improvements to mscom::AgileReference; r=froydnj
This patch adds the definitions of the RefPtr constructor and operator=. It also refactors some stuff in AgileReference to make these objects easier to use. Since it's just a bunch of C++ goop, I figured that you'd be fine to review this. Let me know if you want to add a reviewer who is more familiar with the COM nuances. Depends on D5317 Differential Revision: https://phabricator.services.mozilla.com/D5318 --HG-- extra : moz-landing-system : lando
1 parent e8230a1 commit 061e78a

File tree

2 files changed

+101
-8
lines changed

2 files changed

+101
-8
lines changed

ipc/mscom/AgileReference.cpp

+50-4
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,34 @@ HRESULT WINAPI RoGetAgileReference(AgileReferenceOptions options,
3030
namespace mozilla {
3131
namespace mscom {
3232

33+
AgileReference::AgileReference()
34+
: mIid()
35+
, mGitCookie(0)
36+
{
37+
}
38+
3339
AgileReference::AgileReference(REFIID aIid, IUnknown* aObject)
3440
: mIid(aIid)
3541
, mGitCookie(0)
3642
{
43+
AssignInternal(aObject);
44+
}
45+
46+
void
47+
AgileReference::Assign(REFIID aIid, IUnknown* aObject)
48+
{
49+
Clear();
50+
mIid = aIid;
51+
AssignInternal(aObject);
52+
}
53+
54+
void
55+
AgileReference::AssignInternal(IUnknown* aObject)
56+
{
57+
// We expect mIid to already be set
58+
DebugOnly<IID> zeroIid = {};
59+
MOZ_ASSERT(mIid != zeroIid);
60+
3761
/*
3862
* There are two possible techniques for creating agile references. Starting
3963
* with Windows 8.1, we may use the RoGetAgileReference API, which is faster.
@@ -46,7 +70,7 @@ AgileReference::AgileReference(REFIID aIid, IUnknown* aObject)
4670
MOZ_ASSERT(aObject);
4771

4872
if (pRoGetAgileReference &&
49-
SUCCEEDED(pRoGetAgileReference(AGILEREFERENCE_DEFAULT, aIid, aObject,
73+
SUCCEEDED(pRoGetAgileReference(AGILEREFERENCE_DEFAULT, mIid, aObject,
5074
getter_AddRefs(mAgileRef)))) {
5175
return;
5276
}
@@ -57,7 +81,7 @@ AgileReference::AgileReference(REFIID aIid, IUnknown* aObject)
5781
return;
5882
}
5983

60-
DebugOnly<HRESULT> hr = git->RegisterInterfaceInGlobal(aObject, aIid,
84+
DebugOnly<HRESULT> hr = git->RegisterInterfaceInGlobal(aObject, mIid,
6185
&mGitCookie);
6286
MOZ_ASSERT(SUCCEEDED(hr));
6387
}
@@ -72,7 +96,16 @@ AgileReference::AgileReference(AgileReference&& aOther)
7296

7397
AgileReference::~AgileReference()
7498
{
99+
Clear();
100+
}
101+
102+
void
103+
AgileReference::Clear()
104+
{
105+
mIid = {};
106+
75107
if (!mGitCookie) {
108+
mAgileRef = nullptr;
76109
return;
77110
}
78111

@@ -84,10 +117,23 @@ AgileReference::~AgileReference()
84117

85118
DebugOnly<HRESULT> hr = git->RevokeInterfaceFromGlobal(mGitCookie);
86119
MOZ_ASSERT(SUCCEEDED(hr));
120+
mGitCookie = 0;
121+
}
122+
123+
AgileReference&
124+
AgileReference::operator=(AgileReference&& aOther)
125+
{
126+
Clear();
127+
mIid = aOther.mIid;
128+
aOther.mIid = {};
129+
mAgileRef = std::move(aOther.mAgileRef);
130+
mGitCookie = aOther.mGitCookie;
131+
aOther.mGitCookie = 0;
132+
return *this;
87133
}
88134

89135
HRESULT
90-
AgileReference::Resolve(REFIID aIid, void** aOutInterface)
136+
AgileReference::Resolve(REFIID aIid, void** aOutInterface) const
91137
{
92138
MOZ_ASSERT(aOutInterface);
93139
MOZ_ASSERT(mAgileRef || mGitCookie);
@@ -130,7 +176,7 @@ AgileReference::Resolve(REFIID aIid, void** aOutInterface)
130176
return originalInterface->QueryInterface(aIid, aOutInterface);
131177
}
132178

133-
IGlobalInterfaceTable*
179+
/* static */ IGlobalInterfaceTable*
134180
AgileReference::ObtainGit()
135181
{
136182
// Internally to COM, the Global Interface Table is a singleton, therefore we

ipc/mscom/AgileReference.h

+51-4
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,17 @@ namespace mscom {
3333
* HRESULT hr = myAgileRef->Resolve(IID_IFoo, getter_AddRefs(foo));
3434
* // Now foo may be called from the main thread
3535
*/
36-
class AgileReference
36+
class AgileReference final
3737
{
3838
public:
39+
AgileReference();
40+
41+
template <typename InterfaceT>
42+
explicit AgileReference(RefPtr<InterfaceT>& aObject)
43+
: AgileReference(__uuidof(InterfaceT), aObject)
44+
{
45+
}
46+
3947
AgileReference(REFIID aIid, IUnknown* aObject);
4048
AgileReference(AgileReference&& aOther);
4149

@@ -46,14 +54,31 @@ class AgileReference
4654
return mAgileRef || mGitCookie;
4755
}
4856

49-
HRESULT Resolve(REFIID aIid, void** aOutInterface);
57+
template <typename T>
58+
void Assign(const RefPtr<T>& aOther)
59+
{
60+
Assign(__uuidof(T), aOther);
61+
}
62+
63+
template <typename T>
64+
AgileReference& operator=(const RefPtr<T>& aOther)
65+
{
66+
Assign(aOther);
67+
return *this;
68+
}
69+
70+
HRESULT Resolve(REFIID aIid, void** aOutInterface) const;
5071

5172
AgileReference(const AgileReference& aOther) = delete;
5273
AgileReference& operator=(const AgileReference& aOther) = delete;
53-
AgileReference& operator=(AgileReference&& aOther) = delete;
74+
75+
AgileReference& operator=(AgileReference&& aOther);
5476

5577
private:
56-
IGlobalInterfaceTable* ObtainGit();
78+
void Assign(REFIID aIid, IUnknown* aObject);
79+
void AssignInternal(IUnknown* aObject);
80+
void Clear();
81+
static IGlobalInterfaceTable* ObtainGit();
5782

5883
private:
5984
IID mIid;
@@ -64,4 +89,26 @@ class AgileReference
6489
} // namespace mscom
6590
} // namespace mozilla
6691

92+
template <typename T>
93+
RefPtr<T>::RefPtr(const mozilla::mscom::AgileReference& aAgileRef)
94+
{
95+
void* newRawPtr;
96+
if (FAILED(aAgileRef.Resolve(__uuidof(T), &newRawPtr))) {
97+
newRawPtr = nullptr;
98+
}
99+
mRawPtr = static_cast<T*>(newRawPtr);
100+
}
101+
102+
template <typename T>
103+
RefPtr<T>&
104+
RefPtr<T>::operator=(const mozilla::mscom::AgileReference& aAgileRef)
105+
{
106+
void* newRawPtr;
107+
if (FAILED(aAgileRef.Resolve(__uuidof(T), &newRawPtr))) {
108+
newRawPtr = nullptr;
109+
}
110+
assign_assuming_AddRef(static_cast<T*>(newRawPtr));
111+
return *this;
112+
}
113+
67114
#endif // mozilla_mscom_AgileReference_h

0 commit comments

Comments
 (0)