1/*
2 * Copyright (c) Facebook, Inc. and its affiliates.
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 <cstddef>
20#include <cstdint>
21#include <utility>
22
23#include <folly/lang/Align.h>
24#include <folly/lang/SafeAssert.h>
25
26namespace folly {
27
28/**
29 * Holds a type T, in addition to enough padding to ensure that it isn't subject
30 * to false sharing within the range used by folly.
31 *
32 * If `sizeof(T) <= alignof(T)` then the inner `T` will be entirely within one
33 * false sharing range (AKA cache line).
34 *
35 * CachelinePadded may add padding both before and after the value. Consider
36 * whether alignas(folly::hardware_destructive_interference_size) suffices.
37 */
38template <typename T>
39class CachelinePadded {
40 public:
41 template <typename... Args>
42 explicit CachelinePadded(Args&&... args)
43 : inner_(std::forward<Args>(args)...) {
44 FOLLY_SAFE_DCHECK(
45 (reinterpret_cast<uintptr_t>(&inner_) % alignof(T)) == 0,
46 "CachelinePadded requires types aligned to their ABI requirement");
47 }
48
49 T* get() {
50 return &inner_;
51 }
52
53 const T* get() const {
54 return &inner_;
55 }
56
57 T* operator->() {
58 return get();
59 }
60
61 const T* operator->() const {
62 return get();
63 }
64
65 T& operator*() {
66 return *get();
67 }
68
69 const T& operator*() const {
70 return *get();
71 }
72
73 private:
74 static constexpr size_t paddingSize() noexcept {
75 return hardware_destructive_interference_size -
76 (alignof(T) % hardware_destructive_interference_size);
77 }
78 char paddingPre_[paddingSize()];
79 T inner_;
80 char paddingPost_[paddingSize()];
81};
82} // namespace folly
83