SharedMem.h (5122B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef vm_SharedMem_h 8 #define vm_SharedMem_h 9 10 #include "mozilla/Assertions.h" 11 12 #include <type_traits> 13 14 template <typename T> 15 class SharedMem { 16 static_assert(std::is_pointer_v<T>, "SharedMem encapsulates pointer types"); 17 18 enum Sharedness { IsUnshared, IsShared }; 19 20 T ptr_; 21 #ifdef DEBUG 22 Sharedness sharedness_; 23 #endif 24 25 SharedMem(T ptr, Sharedness sharedness) 26 : ptr_(ptr) 27 #ifdef DEBUG 28 , 29 sharedness_(sharedness) 30 #endif 31 { 32 } 33 34 public: 35 // Create a SharedMem<T> that is an unshared nullptr. 36 SharedMem() 37 : ptr_(nullptr) 38 #ifdef DEBUG 39 , 40 sharedness_(IsUnshared) 41 #endif 42 { 43 } 44 45 // Create a SharedMem<T> that's shared/unshared in the same way as 46 // "forSharedness". 47 SharedMem(T ptr, const SharedMem& forSharedness) 48 : ptr_(ptr) 49 #ifdef DEBUG 50 , 51 sharedness_(forSharedness.sharedness_) 52 #endif 53 { 54 } 55 56 // Create a SharedMem<T> that's marked as shared. 57 static SharedMem shared(void* p) { 58 return SharedMem(static_cast<T>(p), IsShared); 59 } 60 61 // Create a SharedMem<T> that's marked as unshared. 62 static SharedMem unshared(void* p) { 63 return SharedMem(static_cast<T>(p), IsUnshared); 64 } 65 66 SharedMem& operator=(const SharedMem& that) { 67 ptr_ = that.ptr_; 68 #ifdef DEBUG 69 sharedness_ = that.sharedness_; 70 #endif 71 return *this; 72 } 73 74 // Reinterpret-cast the pointer to type U, preserving sharedness. 75 // Eg, "obj->dataPointerEither().cast<uint8_t*>()" yields a 76 // SharedMem<uint8_t*>. 77 template <typename U> 78 inline SharedMem<U> cast() const { 79 #ifdef DEBUG 80 MOZ_ASSERT( 81 asValue() % 82 sizeof(std::conditional_t<std::is_void_v<std::remove_pointer_t<U>>, 83 char, std::remove_pointer_t<U>>) == 84 0); 85 if (sharedness_ == IsUnshared) { 86 return SharedMem<U>::unshared(unwrap()); 87 } 88 #endif 89 return SharedMem<U>::shared(unwrap()); 90 } 91 92 explicit operator bool() const { return ptr_ != nullptr; } 93 94 SharedMem operator+(size_t offset) const { 95 return SharedMem(ptr_ + offset, *this); 96 } 97 98 SharedMem operator-(size_t offset) const { 99 return SharedMem(ptr_ - offset, *this); 100 } 101 102 SharedMem operator++() { 103 ptr_++; 104 return *this; 105 } 106 107 SharedMem operator++(int) { 108 SharedMem<T> result(*this); 109 ptr_++; 110 return result; 111 } 112 113 SharedMem operator--() { 114 ptr_--; 115 return *this; 116 } 117 118 SharedMem operator--(int) { 119 SharedMem<T> result(*this); 120 ptr_--; 121 return result; 122 } 123 124 uintptr_t asValue() const { return reinterpret_cast<uintptr_t>(ptr_); } 125 126 // Cast to char*, add nbytes, and cast back to T. Simplifies code in a few 127 // places. 128 SharedMem addBytes(size_t nbytes) { 129 MOZ_ASSERT( 130 nbytes % 131 sizeof(std::conditional_t<std::is_void_v<std::remove_pointer_t<T>>, 132 char, std::remove_pointer_t<T>>) == 133 0); 134 return SharedMem( 135 reinterpret_cast<T>(reinterpret_cast<char*>(ptr_) + nbytes), *this); 136 } 137 138 T unwrap() const { return ptr_; } 139 140 T unwrapUnshared() const { 141 MOZ_ASSERT(sharedness_ == IsUnshared); 142 return ptr_; 143 } 144 145 uintptr_t unwrapValue() const { return reinterpret_cast<uintptr_t>(ptr_); } 146 }; 147 148 template <typename T> 149 inline bool operator>=(const SharedMem<T>& a, const SharedMem<T>& b) { 150 return a.unwrap() >= b.unwrap(); 151 } 152 153 template <typename T> 154 inline bool operator>=(const void* a, const SharedMem<T>& b) { 155 return a >= b.unwrap(); 156 } 157 158 template <typename T> 159 inline bool operator==(const void* a, const SharedMem<T>& b) { 160 return a == b.unwrap(); 161 } 162 163 template <typename T> 164 inline bool operator==(const SharedMem<T>& a, decltype(nullptr) b) { 165 return a.unwrap() == b; 166 } 167 168 template <typename T> 169 inline bool operator==(const SharedMem<T>& a, const SharedMem<T>& b) { 170 return a.unwrap() == b.unwrap(); 171 } 172 173 template <typename T> 174 inline bool operator!=(const SharedMem<T>& a, decltype(nullptr) b) { 175 return a.unwrap() != b; 176 } 177 178 template <typename T> 179 inline bool operator!=(const SharedMem<T>& a, const SharedMem<T>& b) { 180 return a.unwrap() != b.unwrap(); 181 } 182 183 template <typename T> 184 inline bool operator>(const SharedMem<T>& a, const SharedMem<T>& b) { 185 return a.unwrap() > b.unwrap(); 186 } 187 188 template <typename T> 189 inline bool operator>(const void* a, const SharedMem<T>& b) { 190 return a > b.unwrap(); 191 } 192 193 template <typename T> 194 inline bool operator<=(const SharedMem<T>& a, const SharedMem<T>& b) { 195 return a.unwrap() <= b.unwrap(); 196 } 197 198 template <typename T> 199 inline bool operator<=(const void* a, const SharedMem<T>& b) { 200 return a <= b.unwrap(); 201 } 202 203 template <typename T> 204 inline bool operator<(const SharedMem<T>& a, const SharedMem<T>& b) { 205 return a.unwrap() < b.unwrap(); 206 } 207 208 template <typename T> 209 inline bool operator<(const void* a, const SharedMem<T>& b) { 210 return a < b.unwrap(); 211 } 212 213 #endif // vm_SharedMem_h