• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #include <optional>
18 #ifdef _WIN32
19 #include <windows.h>
20 #elif defined(__APPLE__) || defined(__linux__) || defined(__QNX__)
21 #include <unistd.h>
22 #endif
23 
24 namespace android {
25 namespace base {
26 namespace internal {
27 #ifdef _WIN32
28 struct PlatformTraitWin32 {
29     using DescriptorType = HANDLE;
closeDescriptorandroid::base::internal::PlatformTraitWin3230     void closeDescriptor(DescriptorType handle) { CloseHandle(handle); }
31 };
32 #elif defined(__APPLE__) || defined(__linux__) || defined(__QNX__)
33 struct PlatformTraitUnixLike {
34     using DescriptorType = int;
35     void closeDescriptor(DescriptorType handle) { close(handle); }
36 };
37 #endif
38 }  // namespace internal
39 
40 
41 template <class PlatformTrait>
42 using DescriptorTypeBase = typename PlatformTrait::DescriptorType;
43 
44 // An RAII wrapper for fd on *nix or HANDLE on Windows. The interfaces are similar to std::unique.
45 template <class PlatformTrait>
46 class ManagedDescriptorBase {
47    public:
48     using DescriptorType = typename PlatformTrait::DescriptorType;
49     // The platformTrait argument is only used for testing to inject. platformTrait must live longer
50     // than the created ManagedDescriptorBase object.
ManagedDescriptorBase(DescriptorType rawDescriptor,PlatformTrait & platformTrait=sPlatformTrait)51     ManagedDescriptorBase(DescriptorType rawDescriptor,
52                           PlatformTrait& platformTrait = sPlatformTrait)
53         : mRawDescriptor(rawDescriptor), mPlatformTrait(platformTrait) {}
ManagedDescriptorBase(PlatformTrait & platformTrait=sPlatformTrait)54     ManagedDescriptorBase(PlatformTrait& platformTrait = sPlatformTrait)
55         : mRawDescriptor(std::nullopt), mPlatformTrait(platformTrait) {}
~ManagedDescriptorBase()56     ~ManagedDescriptorBase() {
57         if (!mRawDescriptor.has_value()) {
58             return;
59         }
60         mPlatformTrait.closeDescriptor(*mRawDescriptor);
61     }
62 
63     ManagedDescriptorBase(const ManagedDescriptorBase&) = delete;
64     ManagedDescriptorBase& operator=(const ManagedDescriptorBase&) = delete;
ManagedDescriptorBase(ManagedDescriptorBase && that)65     ManagedDescriptorBase(ManagedDescriptorBase&& that)
66         : mRawDescriptor(std::nullopt), mPlatformTrait(that.mPlatformTrait) {
67         *this = std::move(that);
68     }
operator =(ManagedDescriptorBase && that)69     ManagedDescriptorBase& operator=(ManagedDescriptorBase&& that) {
70         // Assume this->mPlatformTrait and that.mPlatformTrait are the same.
71         if (this == &that) {
72             return *this;
73         }
74 
75         ManagedDescriptorBase other(mPlatformTrait);
76         other.mRawDescriptor = std::move(mRawDescriptor);
77 
78         mRawDescriptor = std::move(that.mRawDescriptor);
79         that.mRawDescriptor = std::nullopt;
80         return *this;
81     }
82 
release()83     std::optional<DescriptorType> release() {
84         std::optional<DescriptorType> res = mRawDescriptor;
85         mRawDescriptor = std::nullopt;
86         return res;
87     }
88 
get()89     std::optional<DescriptorType> get() { return mRawDescriptor; }
90 
91    private:
92     std::optional<DescriptorType> mRawDescriptor;
93     PlatformTrait& mPlatformTrait;
94 
95     // The PlatformTraits singleton used as the default value of the platformTrait parameter in the
96     // constructor.
97     inline static PlatformTrait sPlatformTrait = {};
98 };
99 
100 #ifdef _WIN32
101 using DescriptorType = DescriptorTypeBase<internal::PlatformTraitWin32>;
102 using ManagedDescriptor = ManagedDescriptorBase<internal::PlatformTraitWin32>;
103 #elif defined(__APPLE__) || defined(__linux__) || defined(__QNX__)
104 using DescriptorType = DescriptorTypeBase<internal::PlatformTraitUnixLike>;
105 using ManagedDescriptor = ManagedDescriptorBase<internal::PlatformTraitUnixLike>;
106 #endif
107 
108 }  // namespace base
109 }  // namespace android
110