proxygen
StampedPtr.h
Go to the documentation of this file.
1 /*
2  * Copyright 2017-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 <folly/lang/SafeAssert.h>
20 
21 #include <stdint.h>
22 
23 namespace folly {
24 
62 template <typename T>
63 struct StampedPtr {
69 
70  /* IMPORTANT: default initialization doesn't result in a sane state */
71 
72  T* ptr() const {
73  return unpackPtr(raw);
74  }
75 
76  uint16_t stamp() const {
77  return unpackStamp(raw);
78  }
79 
80  void set(T* ptr, uint16_t stamp) {
81  raw = pack(ptr, stamp);
82  }
83 
84  void setPtr(T* ptr) {
85  raw = pack(ptr, unpackStamp(raw));
86  }
87 
89  raw = pack(unpackPtr(raw), stamp);
90  }
91 
92  static T* unpackPtr(uint64_t raw) {
93  // Canonical form means we need to extend bit 47 of the pointer to
94  // bits 48..63 (unless the operating system never hands those pointers
95  // to us, which is difficult to prove). Signed right-shift of a
96  // negative number is implementation-defined in C++ (not undefined!),
97  // but actually does the right thing on all the platforms I can find.
98  auto extended = static_cast<int64_t>(raw) >> kInternalStampBits;
99  return reinterpret_cast<T*>(static_cast<intptr_t>(extended));
100  }
101 
103  return static_cast<uint16_t>(raw);
104  }
105 
106  static uint64_t pack(T* ptr, uint16_t stamp) {
107  auto shifted = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(ptr))
109  uint64_t raw = shifted | stamp;
110  FOLLY_SAFE_DCHECK(unpackPtr(raw) == ptr, "ptr mismatch.");
111  FOLLY_SAFE_DCHECK(unpackStamp(raw) == stamp, "stamp mismatch.");
112  return raw;
113  }
114 
115  private:
116  // On 32-bit platforms it works okay to store a ptr in the top 48
117  // bits of a 64-bit value, but it will result in unnecessary work.
118  // If we align the pointer part at word granularity when we have the
119  // space then no shifting will ever be needed.
120  static constexpr unsigned kInternalStampBits = sizeof(void*) == 4 ? 32 : 16;
121 };
122 
123 template <typename T>
125  return StampedPtr<T>{StampedPtr<T>::pack(ptr, stamp)};
126 }
127 
128 } // namespace folly
void setPtr(T *ptr)
Definition: StampedPtr.h:84
static uint16_t unpackStamp(uint64_t raw)
Definition: StampedPtr.h:102
StampedPtr< T > makeStampedPtr(T *ptr, uint16_t stamp)
Definition: StampedPtr.h:124
static constexpr unsigned kInternalStampBits
Definition: StampedPtr.h:120
folly::std T
uint16_t stamp() const
Definition: StampedPtr.h:76
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
T * ptr() const
Definition: StampedPtr.h:72
static T * unpackPtr(uint64_t raw)
Definition: StampedPtr.h:92
static uint64_t pack(T *ptr, uint16_t stamp)
Definition: StampedPtr.h:106
#define FOLLY_SAFE_DCHECK(expr, msg)
Definition: SafeAssert.h:42
void setStamp(uint16_t stamp)
Definition: StampedPtr.h:88