proxygen
DiscriminatedPtr.h
Go to the documentation of this file.
1 /*
2  * Copyright 2011-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 
27 #pragma once
28 
29 #include <limits>
30 #include <stdexcept>
31 
32 #include <glog/logging.h>
33 
34 #include <folly/Likely.h>
35 #include <folly/Portability.h>
37 
38 #if !FOLLY_X64 && !FOLLY_AARCH64 && !FOLLY_PPC64
39 #error "DiscriminatedPtr is x64, arm64 and ppc64 specific code."
40 #endif
41 
42 namespace folly {
43 
56 template <typename... Types>
58  // <, not <=, as our indexes are 1-based (0 means "empty")
59  static_assert(
60  sizeof...(Types) < std::numeric_limits<uint16_t>::max(),
61  "too many types");
62 
63  public:
68 
73  template <typename T>
74  explicit DiscriminatedPtr(T* ptr) {
75  set(ptr, typeIndex<T>());
76  }
77 
82  template <typename T>
83  void set(T* ptr) {
84  set(ptr, typeIndex<T>());
85  }
86 
93  template <typename T>
95  void* p = LIKELY(hasType<T>()) ? ptr() : nullptr;
96  return static_cast<T*>(p);
97  }
98 
99  template <typename T>
101  const void* p = LIKELY(hasType<T>()) ? ptr() : nullptr;
102  return static_cast<const T*>(p);
103  }
104 
111  template <typename T>
112  T* get() {
113  if (UNLIKELY(!hasType<T>())) {
114  throw std::invalid_argument("Invalid type");
115  }
116  return static_cast<T*>(ptr());
117  }
118 
119  template <typename T>
120  const T* get() const {
121  if (UNLIKELY(!hasType<T>())) {
122  throw std::invalid_argument("Invalid type");
123  }
124  return static_cast<const T*>(ptr());
125  }
126 
130  bool empty() const {
131  return index() == 0;
132  }
133 
139  template <typename T>
140  bool hasType() const {
141  return index() == typeIndex<T>();
142  }
143 
147  void clear() {
148  data_ = 0;
149  }
150 
154  template <typename T>
156  set(ptr);
157  return *this;
158  }
159 
173  template <typename V>
174  typename dptr_detail::VisitorResult<V, Types...>::type apply(V&& visitor) {
175  size_t n = index();
176  if (n == 0) {
177  throw std::invalid_argument("Empty DiscriminatedPtr");
178  }
179  return dptr_detail::ApplyVisitor<V, Types...>()(
180  n, std::forward<V>(visitor), ptr());
181  }
182 
183  template <typename V>
185  V&& visitor) const {
186  size_t n = index();
187  if (n == 0) {
188  throw std::invalid_argument("Empty DiscriminatedPtr");
189  }
190  return dptr_detail::ApplyConstVisitor<V, Types...>()(
191  n, std::forward<V>(visitor), ptr());
192  }
193 
194  private:
198  template <typename T>
199  uint16_t typeIndex() const {
201  }
202 
203  uint16_t index() const {
204  return data_ >> 48;
205  }
206  void* ptr() const {
207  return reinterpret_cast<void*>(data_ & ((1ULL << 48) - 1));
208  }
209 
210  void set(void* p, uint16_t v) {
211  uintptr_t ip = reinterpret_cast<uintptr_t>(p);
212  CHECK(!(ip >> 48));
213  ip |= static_cast<uintptr_t>(v) << 48;
214  data_ = ip;
215  }
216 
223  uintptr_t data_;
224 };
225 
226 template <typename Visitor, typename... Args>
227 decltype(auto) apply_visitor(
228  Visitor&& visitor,
229  const DiscriminatedPtr<Args...>& variant) {
230  return variant.apply(std::forward<Visitor>(visitor));
231 }
232 
233 template <typename Visitor, typename... Args>
234 decltype(auto) apply_visitor(
235  Visitor&& visitor,
236  DiscriminatedPtr<Args...>& variant) {
237  return variant.apply(std::forward<Visitor>(visitor));
238 }
239 
240 template <typename Visitor, typename... Args>
241 decltype(auto) apply_visitor(
242  Visitor&& visitor,
243  DiscriminatedPtr<Args...>&& variant) {
244  return variant.apply(std::forward<Visitor>(visitor));
245 }
246 
247 } // namespace folly
auto v
LogLevel max
Definition: LogLevel.cpp:31
dptr_detail::VisitorResult< V, Types... >::type apply(V &&visitor)
PskType type
const T * get_nothrow() const noexcept
#define LIKELY(x)
Definition: Likely.h:47
folly::std T
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
dptr_detail::ConstVisitorResult< V, Types... >::type apply(V &&visitor) const
uint16_t typeIndex() const
uint16_t index() const
T * get_nothrow() noexcept
decltype(auto) apply_visitor(Visitor &&visitor, const DiscriminatedPtr< Args... > &variant)
const
Definition: upload.py:398
#define UNLIKELY(x)
Definition: Likely.h:48
DiscriminatedPtr & operator=(T *ptr)