Bug 1828719 - Remove omnijar Gradle project from srcdir r=geckoview-reviewers,nalexan...
[gecko.git] / ipc / mscom / AgileReference.h
blobd39e4444943e8f8289741bbbbc376f8e8987db77
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 #ifndef mozilla_mscom_AgileReference_h
8 #define mozilla_mscom_AgileReference_h
10 #include "mozilla/Attributes.h"
11 #include "mozilla/RefPtr.h"
12 #include "nsISupportsImpl.h"
14 #include <objidl.h>
16 namespace mozilla {
17 namespace mscom {
18 namespace detail {
20 class MOZ_HEAP_CLASS GlobalInterfaceTableCookie final {
21 public:
22 GlobalInterfaceTableCookie(IUnknown* aObject, REFIID aIid,
23 HRESULT& aOutHResult);
25 bool IsValid() const { return !!mCookie; }
26 HRESULT GetInterface(REFIID aIid, void** aOutInterface) const;
28 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GlobalInterfaceTableCookie)
30 GlobalInterfaceTableCookie(const GlobalInterfaceTableCookie&) = delete;
31 GlobalInterfaceTableCookie(GlobalInterfaceTableCookie&&) = delete;
33 GlobalInterfaceTableCookie& operator=(const GlobalInterfaceTableCookie&) =
34 delete;
35 GlobalInterfaceTableCookie& operator=(GlobalInterfaceTableCookie&&) = delete;
37 private:
38 ~GlobalInterfaceTableCookie();
40 private:
41 DWORD mCookie;
43 private:
44 static IGlobalInterfaceTable* ObtainGit();
47 } // namespace detail
49 /**
50 * This class encapsulates an "agile reference." These are references that
51 * allow you to pass COM interfaces between apartments. When you have an
52 * interface that you would like to pass between apartments, you wrap that
53 * interface in an AgileReference and pass the agile reference instead. Then
54 * you unwrap the interface by calling AgileReference::Resolve.
56 * Sample usage:
58 * // In the multithreaded apartment, foo is an IFoo*
59 * auto myAgileRef = MakeUnique<AgileReference>(IID_IFoo, foo);
61 * // myAgileRef is passed to our main thread, which runs in a single-threaded
62 * // apartment:
64 * RefPtr<IFoo> foo;
65 * HRESULT hr = myAgileRef->Resolve(IID_IFoo, getter_AddRefs(foo));
66 * // Now foo may be called from the main thread
68 class AgileReference final {
69 public:
70 AgileReference();
72 template <typename InterfaceT>
73 explicit AgileReference(RefPtr<InterfaceT>& aObject)
74 : AgileReference(__uuidof(InterfaceT), aObject) {}
76 AgileReference(REFIID aIid, IUnknown* aObject);
78 AgileReference(const AgileReference& aOther) = default;
79 AgileReference(AgileReference&& aOther);
81 ~AgileReference();
83 explicit operator bool() const {
84 return mAgileRef || (mGitCookie && mGitCookie->IsValid());
87 HRESULT GetHResult() const { return mHResult; }
89 template <typename T>
90 void Assign(const RefPtr<T>& aOther) {
91 Assign(__uuidof(T), aOther);
94 template <typename T>
95 AgileReference& operator=(const RefPtr<T>& aOther) {
96 Assign(aOther);
97 return *this;
100 HRESULT Resolve(REFIID aIid, void** aOutInterface) const;
102 AgileReference& operator=(const AgileReference& aOther);
103 AgileReference& operator=(AgileReference&& aOther);
105 AgileReference& operator=(decltype(nullptr)) {
106 Clear();
107 return *this;
110 void Clear();
112 private:
113 void Assign(REFIID aIid, IUnknown* aObject);
114 void AssignInternal(IUnknown* aObject);
116 private:
117 IID mIid;
118 RefPtr<IAgileReference> mAgileRef;
119 RefPtr<detail::GlobalInterfaceTableCookie> mGitCookie;
120 HRESULT mHResult;
123 } // namespace mscom
124 } // namespace mozilla
126 template <typename T>
127 RefPtr<T>::RefPtr(const mozilla::mscom::AgileReference& aAgileRef)
128 : mRawPtr(nullptr) {
129 (*this) = aAgileRef;
132 template <typename T>
133 RefPtr<T>& RefPtr<T>::operator=(
134 const mozilla::mscom::AgileReference& aAgileRef) {
135 void* newRawPtr;
136 if (FAILED(aAgileRef.Resolve(__uuidof(T), &newRawPtr))) {
137 newRawPtr = nullptr;
139 assign_assuming_AddRef(static_cast<T*>(newRawPtr));
140 return *this;
143 #endif // mozilla_mscom_AgileReference_h