tor-browser

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

cleanup.h (2722B)


      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 #ifndef ABSL_CLEANUP_INTERNAL_CLEANUP_H_
     16 #define ABSL_CLEANUP_INTERNAL_CLEANUP_H_
     17 
     18 #include <new>
     19 #include <type_traits>
     20 #include <utility>
     21 
     22 #include "absl/base/macros.h"
     23 #include "absl/base/thread_annotations.h"
     24 #include "absl/utility/utility.h"
     25 
     26 namespace absl {
     27 ABSL_NAMESPACE_BEGIN
     28 
     29 namespace cleanup_internal {
     30 
     31 struct Tag {};
     32 
     33 template <typename Arg, typename... Args>
     34 constexpr bool WasDeduced() {
     35  return (std::is_same<cleanup_internal::Tag, Arg>::value) &&
     36         (sizeof...(Args) == 0);
     37 }
     38 
     39 template <typename Callback>
     40 constexpr bool ReturnsVoid() {
     41  return (std::is_same<std::invoke_result_t<Callback>, void>::value);
     42 }
     43 
     44 template <typename Callback>
     45 class Storage {
     46 public:
     47  Storage() = delete;
     48 
     49  explicit Storage(Callback callback) {
     50    // Placement-new into a character buffer is used for eager destruction when
     51    // the cleanup is invoked or cancelled. To ensure this optimizes well, the
     52    // behavior is implemented locally instead of using an absl::optional.
     53    ::new (GetCallbackBuffer()) Callback(std::move(callback));
     54    is_callback_engaged_ = true;
     55  }
     56 
     57  Storage(Storage&& other) {
     58    ABSL_HARDENING_ASSERT(other.IsCallbackEngaged());
     59 
     60    ::new (GetCallbackBuffer()) Callback(std::move(other.GetCallback()));
     61    is_callback_engaged_ = true;
     62 
     63    other.DestroyCallback();
     64  }
     65 
     66  Storage(const Storage& other) = delete;
     67 
     68  Storage& operator=(Storage&& other) = delete;
     69 
     70  Storage& operator=(const Storage& other) = delete;
     71 
     72  void* GetCallbackBuffer() { return static_cast<void*>(callback_buffer_); }
     73 
     74  Callback& GetCallback() {
     75    return *reinterpret_cast<Callback*>(GetCallbackBuffer());
     76  }
     77 
     78  bool IsCallbackEngaged() const { return is_callback_engaged_; }
     79 
     80  void DestroyCallback() {
     81    is_callback_engaged_ = false;
     82    GetCallback().~Callback();
     83  }
     84 
     85  void InvokeCallback() ABSL_NO_THREAD_SAFETY_ANALYSIS {
     86    std::move(GetCallback())();
     87  }
     88 
     89 private:
     90  bool is_callback_engaged_;
     91  alignas(Callback) unsigned char callback_buffer_[sizeof(Callback)];
     92 };
     93 
     94 }  // namespace cleanup_internal
     95 
     96 ABSL_NAMESPACE_END
     97 }  // namespace absl
     98 
     99 #endif  // ABSL_CLEANUP_INTERNAL_CLEANUP_H_