Bug 1860823 [wpt PR 42716] - Update wpt metadata, a=testonly
[gecko.git] / mozglue / misc / DynamicallyLinkedFunctionPtr.h
blob4313974ec5d4d6a1fd0465ab7a682ad5b3c9d05f
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_DynamicallyLinkedFunctionPtr_h
8 #define mozilla_DynamicallyLinkedFunctionPtr_h
10 #include <windows.h>
12 #include <utility>
14 #include "mozilla/Attributes.h"
16 namespace mozilla {
17 namespace detail {
19 template <typename T>
20 struct FunctionPtrCracker;
22 template <typename R, typename... Args>
23 struct FunctionPtrCracker<R (*)(Args...)> {
24 using ReturnT = R;
25 using FunctionPtrT = R (*)(Args...);
28 #if defined(_M_IX86)
29 template <typename R, typename... Args>
30 struct FunctionPtrCracker<R(__stdcall*)(Args...)> {
31 using ReturnT = R;
32 using FunctionPtrT = R(__stdcall*)(Args...);
35 template <typename R, typename... Args>
36 struct FunctionPtrCracker<R(__fastcall*)(Args...)> {
37 using ReturnT = R;
38 using FunctionPtrT = R(__fastcall*)(Args...);
40 #endif // defined(_M_IX86)
42 template <typename T>
43 class DynamicallyLinkedFunctionPtrBase {
44 public:
45 using ReturnT = typename FunctionPtrCracker<T>::ReturnT;
46 using FunctionPtrT = typename FunctionPtrCracker<T>::FunctionPtrT;
48 DynamicallyLinkedFunctionPtrBase(const wchar_t* aLibName,
49 const char* aFuncName)
50 : mModule(::LoadLibraryW(aLibName)), mFunction(nullptr) {
51 if (!mModule) {
52 return;
55 mFunction =
56 reinterpret_cast<FunctionPtrT>(::GetProcAddress(mModule, aFuncName));
58 if (!mFunction) {
59 // Since the function doesn't exist, there is no point in holding a
60 // reference to mModule anymore.
61 ::FreeLibrary(mModule);
62 mModule = nullptr;
66 DynamicallyLinkedFunctionPtrBase(const DynamicallyLinkedFunctionPtrBase&) =
67 delete;
68 DynamicallyLinkedFunctionPtrBase& operator=(
69 const DynamicallyLinkedFunctionPtrBase&) = delete;
71 DynamicallyLinkedFunctionPtrBase(DynamicallyLinkedFunctionPtrBase&&) = delete;
72 DynamicallyLinkedFunctionPtrBase& operator=(
73 DynamicallyLinkedFunctionPtrBase&&) = delete;
75 template <typename... Args>
76 ReturnT operator()(Args&&... args) const {
77 return mFunction(std::forward<Args>(args)...);
80 explicit operator bool() const { return !!mFunction; }
82 protected:
83 HMODULE mModule;
84 FunctionPtrT mFunction;
87 } // namespace detail
89 /**
90 * In most cases, this class is the one that you want to use for resolving a
91 * dynamically-linked function pointer. It should be instantiated as a static
92 * local variable.
94 * NB: It has a trivial destructor, so the DLL that is loaded is never freed.
95 * Assuming that this function is called fairly often, this is the most
96 * sensible option. OTOH, if the function you are calling is a one-off, or the
97 * static local requirement is too restrictive, use DynamicallyLinkedFunctionPtr
98 * instead.
100 template <typename T>
101 class MOZ_STATIC_LOCAL_CLASS StaticDynamicallyLinkedFunctionPtr final
102 : public detail::DynamicallyLinkedFunctionPtrBase<T> {
103 public:
104 StaticDynamicallyLinkedFunctionPtr(const wchar_t* aLibName,
105 const char* aFuncName)
106 : detail::DynamicallyLinkedFunctionPtrBase<T>(aLibName, aFuncName) {}
109 * We only offer this operator for the static local case, as it is not
110 * possible for this object to be destroyed while the returned pointer is
111 * being held.
113 operator typename detail::DynamicallyLinkedFunctionPtrBase<T>::FunctionPtrT()
114 const {
115 return this->mFunction;
119 template <typename T>
120 class MOZ_NON_PARAM MOZ_NON_TEMPORARY_CLASS DynamicallyLinkedFunctionPtr final
121 : public detail::DynamicallyLinkedFunctionPtrBase<T> {
122 public:
123 DynamicallyLinkedFunctionPtr(const wchar_t* aLibName, const char* aFuncName)
124 : detail::DynamicallyLinkedFunctionPtrBase<T>(aLibName, aFuncName) {}
126 ~DynamicallyLinkedFunctionPtr() {
127 if (!this->mModule) {
128 return;
131 ::FreeLibrary(this->mModule);
135 } // namespace mozilla
137 #endif // mozilla_DynamicallyLinkedFunctionPtr_h