/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sts=4 et sw=4 tw=99: * 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 "mozilla/TypeTraits.h" template<typename T> class SharedMem { static_assert(mozilla::IsPointer<T>::value, "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<T> that is an unshared nullptr. SharedMem() : ptr_(nullptr) #ifdef DEBUG , sharedness_(IsUnshared) #endif {} // Create a SharedMem<T> 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<T> that's marked as shared. static SharedMem shared(void* p) { return SharedMem(static_cast<T>(p), IsShared); } // Create a SharedMem<T> that's marked as unshared. static SharedMem unshared(void* p) { return SharedMem(static_cast<T>(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. template<typename U> inline SharedMem<U> cast() const { #ifdef DEBUG MOZ_ASSERT(asValue() % sizeof(mozilla::Conditional<mozilla::IsVoid<typename mozilla::RemovePointer<U>::Type>::value, char, typename mozilla::RemovePointer<U>::Type>) == 0); if (sharedness_ == IsUnshared) return SharedMem<U>::unshared(unwrap()); #endif return SharedMem<U>::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<T> result(*this); ptr_++; return result; } SharedMem operator --() { ptr_--; return *this; } SharedMem operator --(int) { SharedMem<T> result(*this); ptr_--; return result; } uintptr_t asValue() const { return reinterpret_cast<uintptr_t>(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(mozilla::Conditional<mozilla::IsVoid<typename mozilla::RemovePointer<T>::Type>::value, char, typename mozilla::RemovePointer<T>::Type>) == 0); return SharedMem(reinterpret_cast<T>(reinterpret_cast<char*>(ptr_) + nbytes), *this); } T unwrap() const { return ptr_; } T unwrapUnshared() const { MOZ_ASSERT(sharedness_ == IsUnshared); return ptr_; } uintptr_t unwrapValue() const { return reinterpret_cast<uintptr_t>(ptr_); } }; template<typename T> inline bool operator >=(const SharedMem<T>& a, const SharedMem<T>& b) { return a.unwrap() >= b.unwrap(); } template<typename T> inline bool operator >=(const void* a, const SharedMem<T>& b) { return a >= b.unwrap(); } template<typename T> inline bool operator ==(const void* a, const SharedMem<T>& b) { return a == b.unwrap(); } template<typename T> inline bool operator ==(const SharedMem<T>& a, decltype(nullptr) b) { return a.unwrap() == b; } template<typename T> inline bool operator ==(const SharedMem<T>& a, const SharedMem<T>& b) { return a.unwrap() == b.unwrap(); } template<typename T> inline bool operator !=(const SharedMem<T>& a, decltype(nullptr) b) { return a.unwrap() != b; } template<typename T> inline bool operator !=(const SharedMem<T>& a, const SharedMem<T>& b) { return a.unwrap() != b.unwrap(); } template<typename T> inline bool operator >(const SharedMem<T>& a, const SharedMem<T>& b) { return a.unwrap() > b.unwrap(); } template<typename T> inline bool operator >(const void* a, const SharedMem<T>& b) { return a > b.unwrap(); } template<typename T> inline bool operator <=(const SharedMem<T>& a, const SharedMem<T>& b) { return a.unwrap() <= b.unwrap(); } template<typename T> inline bool operator <=(const void* a, const SharedMem<T>& b) { return a <= b.unwrap(); } template<typename T> inline bool operator <(const void* a, const SharedMem<T>& b) { return a < b.unwrap(); } #endif // vm_SharedMem_h