DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (d38398e5144e)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: set ts=2 sw=2 et tw=78:
 * 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/.
 */

/* smart pointer for strong references to objects through pointer-like
 * "handle" objects */

#include <algorithm>
#include "mozilla/Assertions.h"

#ifndef mozilla_HandleRefPtr_h
#define mozilla_HandleRefPtr_h

namespace mozilla {

/**
 * A class for holding strong references to handle-managed objects.
 *
 * This is intended for use with objects like StyleSheetHandle,
 * where the handle type is not a pointer but which can still have
 * ->AddRef() and ->Release() called on it.
 */
template<typename T>
class HandleRefPtr
{
public:
  HandleRefPtr() {}

  HandleRefPtr(HandleRefPtr<T>& aRhs)
  {
    assign(aRhs.mHandle);
  }

  HandleRefPtr(HandleRefPtr<T>&& aRhs)
  {
    std::swap(mHandle, aRhs.mHandle);
  }

  MOZ_IMPLICIT HandleRefPtr(T aRhs)
  {
    assign(aRhs);
  }

  HandleRefPtr<T>& operator=(HandleRefPtr<T>& aRhs)
  {
    assign(aRhs.mHandle);
    return *this;
  }

  HandleRefPtr<T>& operator=(T aRhs)
  {
    assign(aRhs);
    return *this;
  }

  ~HandleRefPtr() { assign(nullptr); }

  explicit operator bool() const { return !!mHandle; }
  bool operator!() const { return !mHandle; }

  operator T() const { return mHandle; }
  T operator->() const { return mHandle; }

  void swap(HandleRefPtr<T>& aOther)
  {
    std::swap(mHandle, aOther.mHandle);
  }

private:
  void assign(T aPtr)
  {
    // AddRef early so |aPtr| can't disappear underneath us.
    if (aPtr) {
      aPtr->AddRef();
    }

    // Don't release |mHandle| yet: if |mHandle| indirectly owns |this|,
    // releasing would invalidate |this|.  Swap |aPtr| for |mHandle| so that
    // |aPtr| lives as long as |this|, then release the new |aPtr| (really the
    // original |mHandle|) so that if |this| is invalidated, we're not using it
    // any more.
    std::swap(mHandle, aPtr);

    if (aPtr) {
      aPtr->Release();
    }
  }

  T mHandle;
};

template<typename T>
inline bool operator==(const HandleRefPtr<T>& aLHS, const HandleRefPtr<T>& aRHS)
{
  return static_cast<T>(aLHS) == static_cast<T>(aRHS);
}

template<typename T>
inline bool operator==(const HandleRefPtr<T>& aLHS, T aRHS)
{
  return static_cast<T>(aLHS) == aRHS;
}

template<typename T>
inline bool operator==(T aLHS, const HandleRefPtr<T>& aRHS)
{
  return aLHS == static_cast<T>(aRHS);
}

template<typename T>
inline bool operator!=(const HandleRefPtr<T>& aLHS, const HandleRefPtr<T>& aRHS)
{
  return !(aLHS == aRHS);
}

template<typename T>
inline bool operator!=(const HandleRefPtr<T>& aLHS, T aRHS)
{
  return !(aLHS == aRHS);
}

template<typename T>
inline bool operator!=(T aLHS, const HandleRefPtr<T>& aRHS)
{
  return !(aLHS == aRHS);
}

} // namespace mozilla

#endif // mozilla_HandleRefPtr_h