proxygen
Indestructible.h
Go to the documentation of this file.
1 /*
2  * Copyright 2016-present Facebook, Inc.
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 #pragma once
18 
19 #include <cassert>
20 #include <type_traits>
21 #include <utility>
22 
23 #include <folly/Traits.h>
24 
25 namespace folly {
26 
27 /***
28  * Indestructible
29  *
30  * When you need a Meyers singleton that will not get destructed, even at
31  * shutdown, and you also want the object stored inline.
32  *
33  * Use like:
34  *
35  * void doSomethingWithExpensiveData();
36  *
37  * void doSomethingWithExpensiveData() {
38  * static const Indestructible<map<string, int>> data{
39  * map<string, int>{{"key1", 17}, {"key2", 19}, {"key3", 23}},
40  * };
41  * callSomethingTakingAMapByRef(*data);
42  * }
43  *
44  * This should be used only for Meyers singletons, and, even then, only when
45  * the instance does not need to be destructed ever.
46  *
47  * This should not be used more generally, e.g., as member fields, etc.
48  *
49  * This is designed as an alternative, but with one fewer allocation at
50  * construction time and one fewer pointer dereference at access time, to the
51  * Meyers singleton pattern of:
52  *
53  * void doSomethingWithExpensiveData() {
54  * static const auto data = // never `delete`d
55  * new map<string, int>{{"key1", 17}, {"key2", 19}, {"key3", 23}};
56  * callSomethingTakingAMapByRef(*data);
57  * }
58  */
59 
60 template <typename T>
61 class Indestructible final {
62  public:
63  template <typename S = T, typename = decltype(S())>
64  constexpr Indestructible() noexcept(noexcept(T())) {}
65 
81  template <
82  typename U = T,
84  _t<std::enable_if<
85  !std::is_same<Indestructible<T>, remove_cvref_t<U>>::value>>* =
86  nullptr,
88  explicit constexpr Indestructible(U&& u) noexcept(
89  noexcept(T(std::declval<U>())))
90  : storage_(std::forward<U>(u)) {}
91  template <
92  typename U = T,
93  _t<std::enable_if<std::is_constructible<T, U&&>::value>>* = nullptr,
94  _t<std::enable_if<
95  !std::is_same<Indestructible<T>, remove_cvref_t<U>>::value>>* =
96  nullptr,
98  /* implicit */ constexpr Indestructible(U&& u) noexcept(
99  noexcept(T(std::declval<U>())))
100  : storage_(std::forward<U>(u)) {}
101 
102  template <typename... Args, typename = decltype(T(std::declval<Args>()...))>
103  explicit constexpr Indestructible(Args&&... args) noexcept(
104  noexcept(T(std::declval<Args>()...)))
105  : storage_(std::forward<Args>(args)...) {}
106  template <
107  typename U,
108  typename... Args,
109  typename = decltype(
110  T(std::declval<std::initializer_list<U>&>(),
111  std::declval<Args>()...))>
112  explicit constexpr Indestructible(std::initializer_list<U> il, Args... args) noexcept(
113  noexcept(
114  T(std::declval<std::initializer_list<U>&>(),
115  std::declval<Args>()...)))
116  : storage_(il, std::forward<Args>(args)...) {}
117 
118  ~Indestructible() = default;
119 
120  Indestructible(Indestructible const&) = delete;
121  Indestructible& operator=(Indestructible const&) = delete;
122 
124  noexcept(T(std::declval<T>())))
125  : storage_(std::move(other.storage_.value)) {
126  other.erased_ = true;
127  }
129  noexcept(T(std::declval<T>()))) {
130  storage_.value = std::move(other.storage_.value);
131  other.erased_ = true;
132  }
133 
134  T* get() noexcept {
135  check();
136  return &storage_.value;
137  }
138  T const* get() const noexcept {
139  check();
140  return &storage_.value;
141  }
143  return *get();
144  }
146  return *get();
147  }
149  return get();
150  }
152  return get();
153  }
154 
155  private:
157  assert(!erased_);
158  }
159 
160  union Storage {
162 
163  template <typename S = T, typename = decltype(S())>
164  constexpr Storage() noexcept(noexcept(T())) : value() {}
165 
166  template <typename... Args, typename = decltype(T(std::declval<Args>()...))>
167  explicit constexpr Storage(Args&&... args) noexcept(
168  noexcept(T(std::declval<Args>()...)))
169  : value(std::forward<Args>(args)...) {}
170 
171  ~Storage() {}
172  };
173 
175  bool erased_{false};
176 };
177 } // namespace folly
typename remove_cvref< T >::type remove_cvref_t
Definition: Traits.h:183
Indestructible & operator=(Indestructible &&other) noexcept(noexcept(T(std::declval< T >())))
T * operator->() noexcept
constexpr Storage() noexcept(noexcept(T()))
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
STL namespace.
folly::std T
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
T const & operator*() const noexcept
requires E e noexcept(noexcept(s.error(std::move(e))))
Indestructible(Indestructible &&other) noexcept(noexcept(T(std::declval< T >())))
constexpr Indestructible(U &&u) noexcept(noexcept(T(std::declval< U >())))
typename T::type _t
Definition: Traits.h:171
constexpr Indestructible(std::initializer_list< U > il, Args...args) noexcept(noexcept(T(std::declval< std::initializer_list< U > & >(), std::declval< Args >()...)))
Indestructible & operator=(Indestructible const &)=delete
constexpr Storage(Args &&...args) noexcept(noexcept(T(std::declval< Args >()...)))
T const * operator->() const noexcept
T & operator*() noexcept
constexpr Indestructible(Args &&...args) noexcept(noexcept(T(std::declval< Args >()...)))
const
Definition: upload.py:398
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
void check() const noexcept
constexpr Indestructible() noexcept(noexcept(T()))