proxygen
Tearable.h
Go to the documentation of this file.
1 /*
2  * Copyright 2018-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 #pragma once
17 
18 #include <atomic>
19 #include <cstring>
20 #include <type_traits>
21 
22 #include <folly/Traits.h>
23 
24 namespace folly {
25 
47 template <typename T>
48 class Tearable {
49  public:
50  // We memcpy the object representation, and the destructor would not know how
51  // to deal with an object state it doesn't understand.
52  static_assert(
54  "Tearable types must be trivially copyable.");
55 
56  Tearable() = default;
57 
58  Tearable(const T& val) : Tearable() {
59  store(val);
60  }
61 
62  // Note that while filling dst with invalid data should be fine, *doing
63  // anything* with the result may trigger undefined behavior unless you've
64  // verified that the data you read was consistent.
65  void load(T& dst) const {
66  RawWord newDst[kNumDataWords];
67 
68  for (std::size_t i = 0; i < kNumDataWords; ++i) {
69  newDst[i] = data_[i].load(std::memory_order_relaxed);
70  }
71  std::memcpy(&dst, newDst, sizeof(T));
72  }
73 
74  void store(const T& val) {
75  RawWord newData[kNumDataWords];
76  std::memcpy(newData, &val, sizeof(T));
77 
78  for (std::size_t i = 0; i < kNumDataWords; ++i) {
79  data_[i].store(newData[i], std::memory_order_relaxed);
80  }
81  }
82 
83  private:
84  // A union gets us memcpy-like copy semantics always.
85  union RawWord {
86  // "unsigned" here matters; we may read uninitialized values (in the
87  // trailing data word in write(), for instance).
88  unsigned char data alignas(void*)[sizeof(void*)];
89  };
90  // Because std::atomic_init is declared but undefined in libstdc++-v4.9.2:
91  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64658.
92  struct AtomicWord : std::atomic<RawWord> {
93  AtomicWord() noexcept : std::atomic<RawWord>{RawWord{}} {}
94  };
95  const static std::size_t kNumDataWords =
96  (sizeof(T) + sizeof(RawWord) - 1) / sizeof(RawWord);
97 
99 };
100 
101 } // namespace folly
void load(T &dst) const
Definition: Tearable.h:65
STL namespace.
double val
Definition: String.cpp:273
folly::std T
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
unsigned char data[sizeof(void *)]
Definition: Tearable.h:88
requires E e noexcept(noexcept(s.error(std::move(e))))
Tearable(const T &val)
Definition: Tearable.h:58
static const std::size_t kNumDataWords
Definition: Tearable.h:95
void store(const T &val)
Definition: Tearable.h:74
std::is_trivially_copyable< T > is_trivially_copyable
Definition: Traits.h:313
Tearable()=default
AtomicWord data_[kNumDataWords]
Definition: Tearable.h:98