tor-browser

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

RefCounted.h (2279B)


      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 js_RefCounted_h
      8 #define js_RefCounted_h
      9 
     10 #include "mozilla/Atomics.h"
     11 #include "mozilla/RefCountType.h"
     12 
     13 #include "js/Utility.h"
     14 
     15 // These types implement the same interface as mozilla::(Atomic)RefCounted and
     16 // must be used instead of mozilla::(Atomic)RefCounted for everything in
     17 // SpiderMonkey. This is because Release() needs to call js_delete, not delete.
     18 
     19 namespace js {
     20 
     21 template <typename T>
     22 class RefCounted {
     23  static const MozRefCountType DEAD = 0xffffdead;
     24 
     25 protected:
     26  RefCounted() : mRefCnt(0) {}
     27  ~RefCounted() { MOZ_ASSERT(mRefCnt == DEAD); }
     28 
     29 public:
     30  void AddRef() const {
     31    MOZ_ASSERT(int32_t(mRefCnt) >= 0);
     32    ++mRefCnt;
     33  }
     34 
     35  void Release() const {
     36    MOZ_ASSERT(int32_t(mRefCnt) > 0);
     37    MozRefCountType cnt = --mRefCnt;
     38    if (0 == cnt) {
     39 #ifdef DEBUG
     40      mRefCnt = DEAD;
     41 #endif
     42      js_delete(const_cast<T*>(static_cast<const T*>(this)));
     43    }
     44  }
     45 
     46 private:
     47  mutable MozRefCountType mRefCnt;
     48 };
     49 
     50 template <typename T>
     51 class AtomicRefCounted {
     52  // On 64-bit systems, if the refcount type is small (say, 32 bits), there's
     53  // a risk that it could overflow.  So require it to be large enough.
     54 
     55  static_assert(sizeof(MozRefCountType) == sizeof(uintptr_t),
     56                "You're at risk for ref count overflow.");
     57 
     58  static const MozRefCountType DEAD = ~MozRefCountType(0xffff) | 0xdead;
     59 
     60 protected:
     61  AtomicRefCounted() = default;
     62  ~AtomicRefCounted() { MOZ_ASSERT(mRefCnt == DEAD); }
     63 
     64 public:
     65  void AddRef() const {
     66    ++mRefCnt;
     67    MOZ_ASSERT(mRefCnt != DEAD);
     68  }
     69 
     70  void Release() const {
     71    MOZ_ASSERT(mRefCnt != 0);
     72    MozRefCountType cnt = --mRefCnt;
     73    if (0 == cnt) {
     74 #ifdef DEBUG
     75      mRefCnt = DEAD;
     76 #endif
     77      js_delete(const_cast<T*>(static_cast<const T*>(this)));
     78    }
     79  }
     80 
     81  bool hasOneRef() const {
     82    MOZ_ASSERT(mRefCnt > 0);
     83    return mRefCnt == 1;
     84  }
     85 
     86 private:
     87  mutable mozilla::Atomic<MozRefCountType> mRefCnt{0};
     88 };
     89 
     90 }  // namespace js
     91 
     92 #endif /* js_RefCounted_h */