Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/xpcom/base/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 16 kB image not shown  

Quelle  nsAutoRef.h   Sprache: C

 
/* -*- 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/. */


// NB: This code may be used from non-XPCOM code, in particular, the
// Windows Default Browser Agent.

#ifndef nsAutoRef_h_
#define nsAutoRef_h_

#include "mozilla/Attributes.h"

template <class T>
class nsSimpleRef;
template <class T>
class nsAutoRefBase;
template <class T>
class nsReturnRef;
template <class T>
class nsReturningRef;

/**
 * template <class T> class nsAutoRef
 *
 * A class that holds a handle to a resource that must be released.
 * No reference is added on construction.
 *
 * No copy constructor nor copy assignment operators are available, so the
 * resource will be held until released on destruction or explicitly
 * |reset()| or transferred through provided methods.
 *
 * The publicly available methods are the public methods on this class and its
 * public base classes |nsAutoRefBase<T>| and |nsSimpleRef<T>|.
 *
 * For function return values see |nsReturnRef<T>|.
 *
 * For each class |T|, |nsAutoRefTraits<T>| or |nsSimpleRef<T>| must be
 * specialized to use |nsAutoRef<T>|.
 *
 * @param T  A class identifying the type of reference held by the
 *           |nsAutoRef<T>| and the unique set methods for managing references
 *           to the resource (defined by |nsAutoRefTraits<T>| or
 *           |nsSimpleRef<T>|).
 *
 *           Often this is the class representing the resource.  Sometimes a
 *           new possibly-incomplete class may need to be declared.
 *
 *
 * Example:  An Automatically closing file descriptor
 *
 * // References that are simple integral types (as file-descriptors are)
 * // usually need a new class to represent the resource and how to handle its
 * // references.
 * class nsRawFD;
 *
 * // Specializing nsAutoRefTraits<nsRawFD> describes how to manage file
 * // descriptors, so that nsAutoRef<nsRawFD> provides automatic closing of
 * // its file descriptor on destruction.
 * template <>
 * class nsAutoRefTraits<nsRawFD> {
 * public:
 *     // The file descriptor is held in an int.
 *     typedef int RawRef;
 *     // -1 means that there is no file associated with the handle.
 *     static int Void() { return -1; }
 *     // The file associated with a file descriptor is released with close().
 *     static void Release(RawRef aFD) { close(aFD); }
 * };
 *
 * // A function returning a file descriptor that must be closed.
 * nsReturnRef<nsRawFD> get_file(const char *filename) {
 *     // Constructing from a raw file descriptor assumes ownership.
 *     nsAutoRef<nsRawFD> fd(open(filename, O_RDONLY));
 *     fcntl(fd, F_SETFD, FD_CLOEXEC);
 *     return fd.out();
 * }
 *
 * void f() {
 *     unsigned char buf[1024];
 *
 *     // Hold a file descriptor for /etc/hosts in fd1.
 *     nsAutoRef<nsRawFD> fd1(get_file("/etc/hosts"));
 *
 *     nsAutoRef<nsRawFD> fd2;
 *     fd2.steal(fd1); // fd2 takes the file descriptor from fd1
 *     ssize_t count = read(fd1, buf, 1024); // error fd1 has no file
 *     count = read(fd2, buf, 1024); // reads from /etc/hosts
 *
 *     // If the file descriptor is not stored then it is closed.
 *     get_file("/etc/login.defs"); // login.defs is closed
 *
 *     // Now use fd1 to hold a file descriptor for /etc/passwd.
 *     fd1 = get_file("/etc/passwd");
 *
 *     // The nsAutoRef<nsRawFD> can give up the file descriptor if explicitly
 *     // instructed, but the caller must then ensure that the file is closed.
 *     int rawfd = fd1.disown();
 *
 *     // Assume ownership of another file descriptor.
 *     fd1.own(open("/proc/1/maps");
 *
 *     // On destruction, fd1 closes /proc/1/maps and fd2 closes /etc/hosts,
 *     // but /etc/passwd is not closed.
 * }
 *
 */


template <class T>
class nsAutoRef : public nsAutoRefBase<T> {
 protected:
  typedef nsAutoRef<T> ThisClass;
  typedef nsAutoRefBase<T> BaseClass;
  typedef nsSimpleRef<T> SimpleRef;
  typedef typename BaseClass::RawRefOnly RawRefOnly;
  typedef typename BaseClass::LocalSimpleRef LocalSimpleRef;

 public:
  nsAutoRef() = default;

  // Explicit construction is required so as not to risk unintentionally
  // releasing the resource associated with a raw ref.
  explicit nsAutoRef(RawRefOnly aRefToRelease) : BaseClass(aRefToRelease) {}

  // Construction from a nsReturnRef<T> function return value, which expects
  // to give up ownership, transfers ownership.
  // (nsReturnRef<T> is converted to const nsReturningRef<T>.)
  explicit nsAutoRef(const nsReturningRef<T>& aReturning)
      : BaseClass(aReturning) {}

  // The only assignment operator provided is for transferring from an
  // nsReturnRef smart reference, which expects to pass its ownership to
  // another object.
  //
  // With raw references and other smart references, the type of the lhs and
  // its taking and releasing nature is often not obvious from an assignment
  // statement.  Assignment from a raw ptr especially is not normally
  // expected to release the reference.
  //
  // Use |steal| for taking ownership from other smart refs.
  //
  // For raw references, use |own| to indicate intention to have the
  // resource released.

  ThisClass& operator=(const nsReturningRef<T>& aReturning) {
    BaseClass::steal(aReturning.mReturnRef);
    return *this;
  }

  // Conversion to a raw reference allow the nsAutoRef<T> to often be used
  // like a raw reference.
  operator typename SimpleRef::RawRef() const { return this->get(); }

  explicit operator bool() const { return this->HaveResource(); }

  // Transfer ownership from another smart reference.
  void steal(ThisClass& aOtherRef) { BaseClass::steal(aOtherRef); }

  // Assume ownership of a raw ref.
  //
  // |own| has similar function to |steal|, and is useful for receiving
  // ownership from a return value of a function.  It is named differently
  // because |own| requires more care to ensure that the function intends to
  // give away ownership, and so that |steal| can be safely used, knowing
  // that it won't steal ownership from any methods returning raw ptrs to
  // data owned by a foreign object.
  void own(RawRefOnly aRefToRelease) { BaseClass::own(aRefToRelease); }

  // Exchange ownership with |aOther|
  void swap(ThisClass& aOther) {
    LocalSimpleRef temp;
    temp.SimpleRef::operator=(*this);
    SimpleRef::operator=(aOther);
    aOther.SimpleRef::operator=(temp);
  }

  // Release the reference now.
  void reset() {
    this->SafeRelease();
    LocalSimpleRef empty;
    SimpleRef::operator=(empty);
  }

  // Pass out the reference for a function return values.
  nsReturnRef<T> out() { return nsReturnRef<T>(this->disown()); }

  // operator->() and disown() are provided by nsAutoRefBase<T>.
  // The default nsSimpleRef<T> provides get().

  // No copy constructor
  explicit nsAutoRef(const ThisClass& aRefToSteal) = delete;
};

/**
 * template <class T> class nsReturnRef
 *
 * A type for function return values that hold a reference to a resource that
 * must be released.  See also |nsAutoRef<T>::out()|.
 */


template <class T>
class nsReturnRef : public nsAutoRefBase<T> {
 protected:
  typedef nsAutoRefBase<T> BaseClass;
  typedef typename BaseClass::RawRefOnly RawRefOnly;

 public:
  // For constructing a return value with no resource
  nsReturnRef() = default;

  // For returning a smart reference from a raw reference that must be
  // released.  Explicit construction is required so as not to risk
  // unintentionally releasing the resource associated with a raw ref.
  MOZ_IMPLICIT nsReturnRef(RawRefOnly aRefToRelease)
      : BaseClass(aRefToRelease) {}

  // Move construction transfers ownership
  nsReturnRef(nsReturnRef<T>&& aRefToSteal) = default;

  MOZ_IMPLICIT nsReturnRef(const nsReturningRef<T>& aReturning)
      : BaseClass(aReturning) {}

  // Conversion to a temporary (const) object referring to this object so
  // that the reference may be passed from a function return value
  // (temporary) to another smart reference.  There is no need to use this
  // explicitly.  Simply assign a nsReturnRef<T> function return value to a
  // smart reference.
  operator nsReturningRef<T>() { return nsReturningRef<T>(*this); }

  // No conversion to RawRef operator is provided on nsReturnRef, to ensure
  // that the return value is not carelessly assigned to a raw ptr (and the
  // resource then released).  If passing to a function that takes a raw
  // ptr, use get or disown as appropriate.
};

/**
 * template <class T> class nsReturningRef
 *
 * A class to allow ownership to be transferred from nsReturnRef function
 * return values.
 *
 * It should not be necessary for clients to reference this
 * class directly.  Simply pass an nsReturnRef<T> to a parameter taking an
 * |nsReturningRef<T>|.
 *
 * The conversion operator on nsReturnRef constructs a temporary wrapper of
 * class nsReturningRef<T> around a non-const reference to the nsReturnRef.
 * The wrapper can then be passed as an rvalue parameter.
 */


template <class T>
class nsReturningRef {
 private:
  friend class nsReturnRef<T>;

  explicit nsReturningRef(nsReturnRef<T>& aReturnRef)
      : mReturnRef(aReturnRef) {}

 public:
  nsReturnRef<T>& mReturnRef;
};

/**
 * template <class T> class nsAutoRefTraits
 *
 * A class describing traits of references managed by the default
 * |nsSimpleRef<T>| implementation and thus |nsAutoRef<T>|.
 * The default |nsSimpleRef<T> is suitable for resources with handles that
 * have a void value.  (If there is no such void value for a handle,
 * specialize |nsSimpleRef<T>|.)
 *
 * Specializations must be provided for each class |T| according to the
 * following pattern:
 *
 * // The template parameter |T| should be a class such that the set of fields
 * // in class nsAutoRefTraits<T> is unique for class |T|.  Usually the
 * // resource object class is sufficient.  For handles that are simple
 * // integral typedefs, a new unique possibly-incomplete class may need to be
 * // declared.
 *
 * template <>
 * class nsAutoRefTraits<T>
 * {
 *     // Specializations must provide a typedef for RawRef, describing the
 *     // type of the handle to the resource.
 *     typedef <handle-type> RawRef;
 *
 *     // Specializations should define Void(), a function returning a value
 *     // suitable for a handle that does not have an associated resource.
 *     //
 *     // The return type must be a suitable as the parameter to a RawRef
 *     // constructor and operator==.
 *     //
 *     // If this method is not accessible then some limited nsAutoRef
 *     // functionality will still be available, but the default constructor,
 *     // |reset|, and most transfer of ownership methods will not be available.
 *     static <return-type> Void();
 *
 *     // Specializations must define Release() to properly finalize the
 *     // handle to a non-void custom-deleted or reference-counted resource.
 *     static void Release(RawRef aRawRef);
 * };
 *
 * See nsPointerRefTraits for example specializations for simple pointer
 * references.  See nsAutoRef for an example specialization for a non-pointer
 * reference.
 */


template <class T>
class nsAutoRefTraits;

/**
 * template <class T> class nsPointerRefTraits
 *
 * A convenience class useful as a base class for specializations of
 * |nsAutoRefTraits<T>| where the handle to the resource is a pointer to |T|.
 * By inheriting from this class, definitions of only Release(RawRef) and
 * possibly AddRef(RawRef) need to be added.
 *
 * Examples of use:
 *
 * template <>
 * class nsAutoRefTraits<PRFileDesc> : public nsPointerRefTraits<PRFileDesc>
 * {
 * public:
 *     static void Release(PRFileDesc *ptr) { PR_Close(ptr); }
 * };
 *
 * template <>
 * class nsAutoRefTraits<FcPattern> : public nsPointerRefTraits<FcPattern>
 * {
 * public:
 *     static void Release(FcPattern *ptr) { FcPatternDestroy(ptr); }
 *     static void AddRef(FcPattern *ptr) { FcPatternReference(ptr); }
 * };
 */


template <class T>
class nsPointerRefTraits {
 public:
  // The handle is a pointer to T.
  typedef T* RawRef;
  // A nullptr does not have a resource.
  static RawRef Void() { return nullptr; }
};

/**
 * template <class T> class nsSimpleRef
 *
 * Constructs a non-smart reference, and provides methods to test whether
 * there is an associated resource and (if so) get its raw handle.
 *
 * A default implementation is suitable for resources with handles that have a
 * void value.  This is not intended for direct use but used by |nsAutoRef<T>|.
 *
 * Specialize this class if there is no particular void value for the resource
 * handle.  A specialized implementation must also provide Release(RawRef),
 */


template <class T>
class nsSimpleRef : protected nsAutoRefTraits<T> {
 protected:
  // The default implementation uses nsAutoRefTrait<T>.
  // Specializations need not define this typedef.
  typedef nsAutoRefTraits<T> Traits;
  // The type of the handle to the resource.
  // A specialization must provide a typedef for RawRef.
  typedef typename Traits::RawRef RawRef;

  // Construct with no resource.
  //
  // If this constructor is not accessible then some limited nsAutoRef
  // functionality will still be available, but the default constructor,
  // |reset|, and most transfer of ownership methods will not be available.
  nsSimpleRef() : mRawRef(Traits::Void()) {}
  // Construct with a handle to a resource.
  // A specialization must provide this.
  explicit nsSimpleRef(RawRef aRawRef) : mRawRef(aRawRef) {}

  // Test whether there is an associated resource.  A specialization must
  // provide this.  The function is permitted to always return true if the
  // default constructor is not accessible, or if Release (and AddRef) can
  // deal with void handles.
  bool HaveResource() const { return mRawRef != Traits::Void(); }

 public:
  // A specialization must provide get() or loose some functionality.  This
  // is inherited by derived classes and the specialization may choose
  // whether it is public or protected.
  RawRef get() const { return mRawRef; }

 private:
  RawRef mRawRef;
};

/**
 * template <class T> class nsAutoRefBase
 *
 * Internal base class for |nsAutoRef<T>| and |nsReturnRef<T>|.
 * Adds release on destruction to a |nsSimpleRef<T>|.
 */


template <class T>
class nsAutoRefBase : public nsSimpleRef<T> {
 protected:
  typedef nsAutoRefBase<T> ThisClass;
  typedef nsSimpleRef<T> SimpleRef;
  typedef typename SimpleRef::RawRef RawRef;

  nsAutoRefBase() = default;

  // A type for parameters that should be passed a raw ref but should not
  // accept implicit conversions (from another smart ref).  (The only
  // conversion to this type is from a raw ref so only raw refs will be
  // accepted.)
  class RawRefOnly {
   public:
    MOZ_IMPLICIT RawRefOnly(RawRef aRawRef) : mRawRef(aRawRef) {}
    operator RawRef() const { return mRawRef; }

   private:
    RawRef mRawRef;
  };

  // Construction from a raw ref assumes ownership
  explicit nsAutoRefBase(RawRefOnly aRefToRelease) : SimpleRef(aRefToRelease) {}

  // Constructors that steal ownership
  nsAutoRefBase(ThisClass&& aRefToSteal) : SimpleRef(aRefToSteal.disown()) {}
  explicit nsAutoRefBase(const nsReturningRef<T>& aReturning)
      : SimpleRef(aReturning.mReturnRef.disown()) {}

  ~nsAutoRefBase() { SafeRelease(); }

  // An internal class providing access to protected nsSimpleRef<T>
  // constructors for construction of temporary simple references (that are
  // not ThisClass).
  class LocalSimpleRef : public SimpleRef {
   public:
    LocalSimpleRef() = default;
    explicit LocalSimpleRef(RawRef aRawRef) : SimpleRef(aRawRef) {}
  };

 public:
  ThisClass& operator=(const ThisClass& aSmartRef) = delete;

  RawRef operator->() const { return this->get(); }

  // Transfer ownership to a raw reference.
  //
  // THE CALLER MUST ENSURE THAT THE REFERENCE IS EXPLICITLY RELEASED.
  //
  // Is this really what you want to use?  Using this removes any guarantee
  // of release.  Use nsAutoRef<T>::out() for return values, or an
  // nsAutoRef<T> modifiable lvalue for an out parameter.  Use disown() when
  // the reference must be stored in a POD type object, such as may be
  // preferred for a namespace-scope object with static storage duration,
  // for example.
  RawRef disown() {
    RawRef temp = this->get();
    LocalSimpleRef empty;
    SimpleRef::operator=(empty);
    return temp;
  }

 protected:
  // steal and own are protected because they make no sense on nsReturnRef,
  // but steal is implemented on this class for access to aOtherRef.disown()
  // when aOtherRef is an nsReturnRef;

  // Transfer ownership from another smart reference.
  void steal(ThisClass& aOtherRef) { own(aOtherRef.disown()); }
  // Assume ownership of a raw ref.
  void own(RawRefOnly aRefToRelease) {
    SafeRelease();
    LocalSimpleRef ref(aRefToRelease);
    SimpleRef::operator=(ref);
  }

  // Release a resource if there is one.
  void SafeRelease() {
    if (this->HaveResource()) {
      this->Release(this->get());
    }
  }
};

#endif  // !defined(nsAutoRef_h_)

100%


¤ Dauer der Verarbeitung: 0.29 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.