/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: set ts=8 sts=2 et sw=2 tw=80: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef vm_SharedMem_h #define vm_SharedMem_h #include template class SharedMem { static_assert(std::is_pointer_v, "SharedMem encapsulates pointer types"); enum Sharedness { IsUnshared, IsShared }; T ptr_; #ifdef DEBUG Sharedness sharedness_; #endif SharedMem(T ptr, Sharedness sharedness) : ptr_(ptr) #ifdef DEBUG , sharedness_(sharedness) #endif { } public: // Create a SharedMem that is an unshared nullptr. SharedMem() : ptr_(nullptr) #ifdef DEBUG , sharedness_(IsUnshared) #endif { } // Create a SharedMem that's shared/unshared in the same way as // "forSharedness". SharedMem(T ptr, const SharedMem& forSharedness) : ptr_(ptr) #ifdef DEBUG , sharedness_(forSharedness.sharedness_) #endif { } // Create a SharedMem that's marked as shared. static SharedMem shared(void* p) { return SharedMem(static_cast(p), IsShared); } // Create a SharedMem that's marked as unshared. static SharedMem unshared(void* p) { return SharedMem(static_cast(p), IsUnshared); } SharedMem& operator=(const SharedMem& that) { ptr_ = that.ptr_; #ifdef DEBUG sharedness_ = that.sharedness_; #endif return *this; } // Reinterpret-cast the pointer to type U, preserving sharedness. // Eg, "obj->dataPointerEither().cast()" yields a // SharedMem. template inline SharedMem cast() const { #ifdef DEBUG MOZ_ASSERT( asValue() % sizeof(std::conditional_t>, char, std::remove_pointer_t>) == 0); if (sharedness_ == IsUnshared) { return SharedMem::unshared(unwrap()); } #endif return SharedMem::shared(unwrap()); } explicit operator bool() { return ptr_ != nullptr; } SharedMem operator+(size_t offset) { return SharedMem(ptr_ + offset, *this); } SharedMem operator-(size_t offset) { return SharedMem(ptr_ - offset, *this); } SharedMem operator++() { ptr_++; return *this; } SharedMem operator++(int) { SharedMem result(*this); ptr_++; return result; } SharedMem operator--() { ptr_--; return *this; } SharedMem operator--(int) { SharedMem result(*this); ptr_--; return result; } uintptr_t asValue() const { return reinterpret_cast(ptr_); } // Cast to char*, add nbytes, and cast back to T. Simplifies code in a few // places. SharedMem addBytes(size_t nbytes) { MOZ_ASSERT( nbytes % sizeof(std::conditional_t>, char, std::remove_pointer_t>) == 0); return SharedMem( reinterpret_cast(reinterpret_cast(ptr_) + nbytes), *this); } T unwrap() const { return ptr_; } T unwrapUnshared() const { MOZ_ASSERT(sharedness_ == IsUnshared); return ptr_; } uintptr_t unwrapValue() const { return reinterpret_cast(ptr_); } }; template inline bool operator>=(const SharedMem& a, const SharedMem& b) { return a.unwrap() >= b.unwrap(); } template inline bool operator>=(const void* a, const SharedMem& b) { return a >= b.unwrap(); } template inline bool operator==(const void* a, const SharedMem& b) { return a == b.unwrap(); } template inline bool operator==(const SharedMem& a, decltype(nullptr) b) { return a.unwrap() == b; } template inline bool operator==(const SharedMem& a, const SharedMem& b) { return a.unwrap() == b.unwrap(); } template inline bool operator!=(const SharedMem& a, decltype(nullptr) b) { return a.unwrap() != b; } template inline bool operator!=(const SharedMem& a, const SharedMem& b) { return a.unwrap() != b.unwrap(); } template inline bool operator>(const SharedMem& a, const SharedMem& b) { return a.unwrap() > b.unwrap(); } template inline bool operator>(const void* a, const SharedMem& b) { return a > b.unwrap(); } template inline bool operator<=(const SharedMem& a, const SharedMem& b) { return a.unwrap() <= b.unwrap(); } template inline bool operator<=(const void* a, const SharedMem& b) { return a <= b.unwrap(); } template inline bool operator<(const void* a, const SharedMem& b) { return a < b.unwrap(); } #endif // vm_SharedMem_h