|
||||
File indexing completed on 2025-01-18 09:27:09
0001 // Copyright 2021 The Abseil Authors. 0002 // 0003 // Licensed under the Apache License, Version 2.0 (the "License"); 0004 // you may not use this file except in compliance with the License. 0005 // You may obtain a copy of the License at 0006 // 0007 // https://www.apache.org/licenses/LICENSE-2.0 0008 // 0009 // Unless required by applicable law or agreed to in writing, software 0010 // distributed under the License is distributed on an "AS IS" BASIS, 0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0012 // See the License for the specific language governing permissions and 0013 // limitations under the License. 0014 // 0015 // ----------------------------------------------------------------------------- 0016 // File: cleanup.h 0017 // ----------------------------------------------------------------------------- 0018 // 0019 // `absl::Cleanup` implements the scope guard idiom, invoking the contained 0020 // callback's `operator()() &&` on scope exit. 0021 // 0022 // Example: 0023 // 0024 // ``` 0025 // absl::Status CopyGoodData(const char* source_path, const char* sink_path) { 0026 // FILE* source_file = fopen(source_path, "r"); 0027 // if (source_file == nullptr) { 0028 // return absl::NotFoundError("No source file"); // No cleanups execute 0029 // } 0030 // 0031 // // C++17 style cleanup using class template argument deduction 0032 // absl::Cleanup source_closer = [source_file] { fclose(source_file); }; 0033 // 0034 // FILE* sink_file = fopen(sink_path, "w"); 0035 // if (sink_file == nullptr) { 0036 // return absl::NotFoundError("No sink file"); // First cleanup executes 0037 // } 0038 // 0039 // // C++11 style cleanup using the factory function 0040 // auto sink_closer = absl::MakeCleanup([sink_file] { fclose(sink_file); }); 0041 // 0042 // Data data; 0043 // while (ReadData(source_file, &data)) { 0044 // if (!data.IsGood()) { 0045 // absl::Status result = absl::FailedPreconditionError("Read bad data"); 0046 // return result; // Both cleanups execute 0047 // } 0048 // SaveData(sink_file, &data); 0049 // } 0050 // 0051 // return absl::OkStatus(); // Both cleanups execute 0052 // } 0053 // ``` 0054 // 0055 // Methods: 0056 // 0057 // `std::move(cleanup).Cancel()` will prevent the callback from executing. 0058 // 0059 // `std::move(cleanup).Invoke()` will execute the callback early, before 0060 // destruction, and prevent the callback from executing in the destructor. 0061 // 0062 // Usage: 0063 // 0064 // `absl::Cleanup` is not an interface type. It is only intended to be used 0065 // within the body of a function. It is not a value type and instead models a 0066 // control flow construct. Check out `defer` in Golang for something similar. 0067 0068 #ifndef ABSL_CLEANUP_CLEANUP_H_ 0069 #define ABSL_CLEANUP_CLEANUP_H_ 0070 0071 #include <utility> 0072 0073 #include "absl/base/config.h" 0074 #include "absl/base/macros.h" 0075 #include "absl/cleanup/internal/cleanup.h" 0076 0077 namespace absl { 0078 ABSL_NAMESPACE_BEGIN 0079 0080 template <typename Arg, typename Callback = void()> 0081 class ABSL_MUST_USE_RESULT Cleanup final { 0082 static_assert(cleanup_internal::WasDeduced<Arg>(), 0083 "Explicit template parameters are not supported."); 0084 0085 static_assert(cleanup_internal::ReturnsVoid<Callback>(), 0086 "Callbacks that return values are not supported."); 0087 0088 public: 0089 Cleanup(Callback callback) : storage_(std::move(callback)) {} // NOLINT 0090 0091 Cleanup(Cleanup&& other) = default; 0092 0093 void Cancel() && { 0094 ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged()); 0095 storage_.DestroyCallback(); 0096 } 0097 0098 void Invoke() && { 0099 ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged()); 0100 storage_.InvokeCallback(); 0101 storage_.DestroyCallback(); 0102 } 0103 0104 ~Cleanup() { 0105 if (storage_.IsCallbackEngaged()) { 0106 storage_.InvokeCallback(); 0107 storage_.DestroyCallback(); 0108 } 0109 } 0110 0111 private: 0112 cleanup_internal::Storage<Callback> storage_; 0113 }; 0114 0115 // `absl::Cleanup c = /* callback */;` 0116 // 0117 // C++17 type deduction API for creating an instance of `absl::Cleanup` 0118 #if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION) 0119 template <typename Callback> 0120 Cleanup(Callback callback) -> Cleanup<cleanup_internal::Tag, Callback>; 0121 #endif // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION) 0122 0123 // `auto c = absl::MakeCleanup(/* callback */);` 0124 // 0125 // C++11 type deduction API for creating an instance of `absl::Cleanup` 0126 template <typename... Args, typename Callback> 0127 absl::Cleanup<cleanup_internal::Tag, Callback> MakeCleanup(Callback callback) { 0128 static_assert(cleanup_internal::WasDeduced<cleanup_internal::Tag, Args...>(), 0129 "Explicit template parameters are not supported."); 0130 0131 static_assert(cleanup_internal::ReturnsVoid<Callback>(), 0132 "Callbacks that return values are not supported."); 0133 0134 return {std::move(callback)}; 0135 } 0136 0137 ABSL_NAMESPACE_END 0138 } // namespace absl 0139 0140 #endif // ABSL_CLEANUP_CLEANUP_H_
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |