tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

cleanup.h (4514B)


      1 // Copyright 2021 The Abseil Authors.
      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 //      https://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 // -----------------------------------------------------------------------------
     16 // File: cleanup.h
     17 // -----------------------------------------------------------------------------
     18 //
     19 // `absl::Cleanup` implements the scope guard idiom, invoking the contained
     20 // callback's `operator()() &&` on scope exit.
     21 //
     22 // Example:
     23 //
     24 // ```
     25 //   absl::Status CopyGoodData(const char* source_path, const char* sink_path) {
     26 //     FILE* source_file = fopen(source_path, "r");
     27 //     if (source_file == nullptr) {
     28 //       return absl::NotFoundError("No source file");  // No cleanups execute
     29 //     }
     30 //
     31 //     // C++17 style cleanup using class template argument deduction
     32 //     absl::Cleanup source_closer = [source_file] { fclose(source_file); };
     33 //
     34 //     FILE* sink_file = fopen(sink_path, "w");
     35 //     if (sink_file == nullptr) {
     36 //       return absl::NotFoundError("No sink file");  // First cleanup executes
     37 //     }
     38 //
     39 //     // C++11 style cleanup using the factory function
     40 //     auto sink_closer = absl::MakeCleanup([sink_file] { fclose(sink_file); });
     41 //
     42 //     Data data;
     43 //     while (ReadData(source_file, &data)) {
     44 //       if (!data.IsGood()) {
     45 //         absl::Status result = absl::FailedPreconditionError("Read bad data");
     46 //         return result;  // Both cleanups execute
     47 //       }
     48 //       SaveData(sink_file, &data);
     49 //     }
     50 //
     51 //     return absl::OkStatus();  // Both cleanups execute
     52 //   }
     53 // ```
     54 //
     55 // Methods:
     56 //
     57 // `std::move(cleanup).Cancel()` will prevent the callback from executing.
     58 //
     59 // `std::move(cleanup).Invoke()` will execute the callback early, before
     60 // destruction, and prevent the callback from executing in the destructor.
     61 //
     62 // Usage:
     63 //
     64 // `absl::Cleanup` is not an interface type. It is only intended to be used
     65 // within the body of a function. It is not a value type and instead models a
     66 // control flow construct. Check out `defer` in Golang for something similar.
     67 
     68 #ifndef ABSL_CLEANUP_CLEANUP_H_
     69 #define ABSL_CLEANUP_CLEANUP_H_
     70 
     71 #include <utility>
     72 
     73 #include "absl/base/config.h"
     74 #include "absl/base/macros.h"
     75 #include "absl/cleanup/internal/cleanup.h"
     76 
     77 namespace absl {
     78 ABSL_NAMESPACE_BEGIN
     79 
     80 template <typename Arg, typename Callback = void()>
     81 class [[nodiscard]] Cleanup final {
     82  static_assert(cleanup_internal::WasDeduced<Arg>(),
     83                "Explicit template parameters are not supported.");
     84 
     85  static_assert(cleanup_internal::ReturnsVoid<Callback>(),
     86                "Callbacks that return values are not supported.");
     87 
     88 public:
     89  Cleanup(Callback callback) : storage_(std::move(callback)) {}  // NOLINT
     90 
     91  Cleanup(Cleanup&& other) = default;
     92 
     93  void Cancel() && {
     94    ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged());
     95    storage_.DestroyCallback();
     96  }
     97 
     98  void Invoke() && {
     99    ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged());
    100    storage_.InvokeCallback();
    101    storage_.DestroyCallback();
    102  }
    103 
    104  ~Cleanup() {
    105    if (storage_.IsCallbackEngaged()) {
    106      storage_.InvokeCallback();
    107      storage_.DestroyCallback();
    108    }
    109  }
    110 
    111 private:
    112  cleanup_internal::Storage<Callback> storage_;
    113 };
    114 
    115 // `absl::Cleanup c = /* callback */;`
    116 //
    117 // C++17 type deduction API for creating an instance of `absl::Cleanup`
    118 template <typename Callback>
    119 Cleanup(Callback callback) -> Cleanup<cleanup_internal::Tag, Callback>;
    120 
    121 // `auto c = absl::MakeCleanup(/* callback */);`
    122 //
    123 // C++11 type deduction API for creating an instance of `absl::Cleanup`
    124 template <typename... Args, typename Callback>
    125 absl::Cleanup<cleanup_internal::Tag, Callback> MakeCleanup(Callback callback) {
    126  static_assert(cleanup_internal::WasDeduced<cleanup_internal::Tag, Args...>(),
    127                "Explicit template parameters are not supported.");
    128 
    129  static_assert(cleanup_internal::ReturnsVoid<Callback>(),
    130                "Callbacks that return values are not supported.");
    131 
    132  return {std::move(callback)};
    133 }
    134 
    135 ABSL_NAMESPACE_END
    136 }  // namespace absl
    137 
    138 #endif  // ABSL_CLEANUP_CLEANUP_H_