Back to home page

EIC code displayed by LXR

 
 

    


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_