1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef INCLUDE_PERFETTO_EXT_BASE_SCOPED_FILE_H_ 18 #define INCLUDE_PERFETTO_EXT_BASE_SCOPED_FILE_H_ 19 20 #include "perfetto/base/build_config.h" 21 22 #include <stdio.h> 23 24 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 25 #include <dirent.h> // For DIR* / opendir(). 26 #endif 27 28 #include <string> 29 30 #include "perfetto/base/export.h" 31 #include "perfetto/base/logging.h" 32 #include "perfetto/base/platform_handle.h" 33 34 namespace perfetto { 35 namespace base { 36 37 namespace internal { 38 // Used for the most common cases of ScopedResource where there is only one 39 // invalid value. 40 template <typename T, T InvalidValue> 41 struct DefaultValidityChecker { IsValidDefaultValidityChecker42 static bool IsValid(T t) { return t != InvalidValue; } 43 }; 44 } // namespace internal 45 46 // RAII classes for auto-releasing fds and dirs. 47 // if T is a pointer type, InvalidValue must be nullptr. Doing otherwise 48 // causes weird unexpected behaviors (See https://godbolt.org/z/5nGMW4). 49 template <typename T, 50 int (*CloseFunction)(T), 51 T InvalidValue, 52 bool CheckClose = true, 53 class Checker = internal::DefaultValidityChecker<T, InvalidValue>> 54 class PERFETTO_EXPORT ScopedResource { 55 public: 56 using ValidityChecker = Checker; 57 static constexpr T kInvalid = InvalidValue; 58 t_(t)59 explicit ScopedResource(T t = InvalidValue) : t_(t) {} ScopedResource(ScopedResource && other)60 ScopedResource(ScopedResource&& other) noexcept { 61 t_ = other.t_; 62 other.t_ = InvalidValue; 63 } 64 ScopedResource& operator=(ScopedResource&& other) { 65 reset(other.t_); 66 other.t_ = InvalidValue; 67 return *this; 68 } get()69 T get() const { return t_; } 70 T operator*() const { return t_; } 71 explicit operator bool() const { return Checker::IsValid(t_); } 72 void reset(T r = InvalidValue) { 73 if (Checker::IsValid(t_)) { 74 int res = CloseFunction(t_); 75 if (CheckClose) 76 PERFETTO_CHECK(res == 0); 77 } 78 t_ = r; 79 } release()80 T release() { 81 T t = t_; 82 t_ = InvalidValue; 83 return t; 84 } ~ScopedResource()85 ~ScopedResource() { reset(InvalidValue); } 86 87 private: 88 ScopedResource(const ScopedResource&) = delete; 89 ScopedResource& operator=(const ScopedResource&) = delete; 90 T t_; 91 }; 92 93 // Declared in file_utils.h. Forward declared to avoid #include cycles. 94 int PERFETTO_EXPORT CloseFile(int fd); 95 96 // Use this for file resources obtained via open() and similar APIs. 97 using ScopedFile = ScopedResource<int, CloseFile, -1>; 98 using ScopedFstream = ScopedResource<FILE*, fclose, nullptr>; 99 100 // Use this for resources that are HANDLE on Windows. See comments in 101 // platform_handle.h 102 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN) 103 using ScopedPlatformHandle = ScopedResource<PlatformHandle, 104 ClosePlatformHandle, 105 /*InvalidValue=*/nullptr, 106 /*CheckClose=*/true, 107 PlatformHandleChecker>; 108 #else 109 // On non-windows systems we alias ScopedPlatformHandle to ScopedFile because 110 // they are really the same. This is to allow assignments between the two in 111 // Linux-specific code paths that predate ScopedPlatformHandle. 112 static_assert(std::is_same<int, PlatformHandle>::value, ""); 113 using ScopedPlatformHandle = ScopedFile; 114 115 // DIR* does not exist on Windows. 116 using ScopedDir = ScopedResource<DIR*, closedir, nullptr>; 117 #endif 118 119 } // namespace base 120 } // namespace perfetto 121 122 #endif // INCLUDE_PERFETTO_EXT_BASE_SCOPED_FILE_H_ 123