tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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