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/. */
10 #include "mozilla/Attributes.h"
12 #include "nscore.h" // for nullptr, bool
14 template <class T
> class nsSimpleRef
;
15 template <class T
> class nsAutoRefBase
;
16 template <class T
> class nsReturnRef
;
17 template <class T
> class nsReturningRef
;
20 * template <class T> class nsAutoRef
22 * A class that holds a handle to a resource that must be released.
23 * No reference is added on construction.
25 * No copy constructor nor copy assignment operators are available, so the
26 * resource will be held until released on destruction or explicitly
27 * |reset()| or transferred through provided methods.
29 * The publicly available methods are the public methods on this class and its
30 * public base classes |nsAutoRefBase<T>| and |nsSimpleRef<T>|.
32 * For ref-counted resources see also |nsCountedRef<T>|.
33 * For function return values see |nsReturnRef<T>|.
35 * For each class |T|, |nsAutoRefTraits<T>| or |nsSimpleRef<T>| must be
36 * specialized to use |nsAutoRef<T>| and |nsCountedRef<T>|.
38 * @param T A class identifying the type of reference held by the
39 * |nsAutoRef<T>| and the unique set methods for managing references
40 * to the resource (defined by |nsAutoRefTraits<T>| or
43 * Often this is the class representing the resource. Sometimes a
44 * new possibly-incomplete class may need to be declared.
47 * Example: An Automatically closing file descriptor
49 * // References that are simple integral types (as file-descriptors are)
50 * // usually need a new class to represent the resource and how to handle its
54 * // Specializing nsAutoRefTraits<nsRawFD> describes how to manage file
55 * // descriptors, so that nsAutoRef<nsRawFD> provides automatic closing of
56 * // its file descriptor on destruction.
58 * class nsAutoRefTraits<nsRawFD> {
60 * // The file descriptor is held in an int.
62 * // -1 means that there is no file associated with the handle.
63 * static int Void() { return -1; }
64 * // The file associated with a file descriptor is released with close().
65 * static void Release(RawRef aFD) { close(aFD); }
68 * // A function returning a file descriptor that must be closed.
69 * nsReturnRef<nsRawFD> get_file(const char *filename) {
70 * // Constructing from a raw file descriptor assumes ownership.
71 * nsAutoRef<nsRawFD> fd(open(filename, O_RDONLY));
72 * fcntl(fd, F_SETFD, FD_CLOEXEC);
77 * unsigned char buf[1024];
79 * // Hold a file descriptor for /etc/hosts in fd1.
80 * nsAutoRef<nsRawFD> fd1(get_file("/etc/hosts"));
82 * nsAutoRef<nsRawFD> fd2;
83 * fd2.steal(fd1); // fd2 takes the file descriptor from fd1
84 * ssize_t count = read(fd1, buf, 1024); // error fd1 has no file
85 * count = read(fd2, buf, 1024); // reads from /etc/hosts
87 * // If the file descriptor is not stored then it is closed.
88 * get_file("/etc/login.defs"); // login.defs is closed
90 * // Now use fd1 to hold a file descriptor for /etc/passwd.
91 * fd1 = get_file("/etc/passwd");
93 * // The nsAutoRef<nsRawFD> can give up the file descriptor if explicitly
94 * // instructed, but the caller must then ensure that the file is closed.
95 * int rawfd = fd1.disown();
97 * // Assume ownership of another file descriptor.
98 * fd1.own(open("/proc/1/maps");
100 * // On destruction, fd1 closes /proc/1/maps and fd2 closes /etc/hosts,
101 * // but /etc/passwd is not closed.
108 class nsAutoRef
: public nsAutoRefBase
<T
>
111 typedef nsAutoRef
<T
> ThisClass
;
112 typedef nsAutoRefBase
<T
> BaseClass
;
113 typedef nsSimpleRef
<T
> SimpleRef
;
114 typedef typename
BaseClass::RawRefOnly RawRefOnly
;
115 typedef typename
BaseClass::LocalSimpleRef LocalSimpleRef
;
122 // Explicit construction is required so as not to risk unintentionally
123 // releasing the resource associated with a raw ref.
124 explicit nsAutoRef(RawRefOnly aRefToRelease
)
125 : BaseClass(aRefToRelease
)
129 // Construction from a nsReturnRef<T> function return value, which expects
130 // to give up ownership, transfers ownership.
131 // (nsReturnRef<T> is converted to const nsReturningRef<T>.)
132 explicit nsAutoRef(const nsReturningRef
<T
>& aReturning
)
133 : BaseClass(aReturning
)
137 // The only assignment operator provided is for transferring from an
138 // nsReturnRef smart reference, which expects to pass its ownership to
141 // With raw references and other smart references, the type of the lhs and
142 // its taking and releasing nature is often not obvious from an assignment
143 // statement. Assignment from a raw ptr especially is not normally
144 // expected to release the reference.
146 // Use |steal| for taking ownership from other smart refs.
148 // For raw references, use |own| to indicate intention to have the
149 // resource released.
151 // Or, to create another owner of the same reference, use an nsCountedRef.
153 ThisClass
& operator=(const nsReturningRef
<T
>& aReturning
)
155 BaseClass::steal(aReturning
.mReturnRef
);
159 // Conversion to a raw reference allow the nsAutoRef<T> to often be used
160 // like a raw reference.
161 operator typename
SimpleRef::RawRef() const
166 // Transfer ownership from another smart reference.
167 void steal(ThisClass
& aOtherRef
)
169 BaseClass::steal(aOtherRef
);
172 // Assume ownership of a raw ref.
174 // |own| has similar function to |steal|, and is useful for receiving
175 // ownership from a return value of a function. It is named differently
176 // because |own| requires more care to ensure that the function intends to
177 // give away ownership, and so that |steal| can be safely used, knowing
178 // that it won't steal ownership from any methods returning raw ptrs to
179 // data owned by a foreign object.
180 void own(RawRefOnly aRefToRelease
)
182 BaseClass::own(aRefToRelease
);
185 // Exchange ownership with |aOther|
186 void swap(ThisClass
& aOther
)
189 temp
.SimpleRef::operator=(*this);
190 SimpleRef::operator=(aOther
);
191 aOther
.SimpleRef::operator=(temp
);
194 // Release the reference now.
198 LocalSimpleRef empty
;
199 SimpleRef::operator=(empty
);
202 // Pass out the reference for a function return values.
205 return nsReturnRef
<T
>(this->disown());
208 // operator->() and disown() are provided by nsAutoRefBase<T>.
209 // The default nsSimpleRef<T> provides get().
212 // No copy constructor
213 explicit nsAutoRef(ThisClass
& aRefToSteal
);
217 * template <class T> class nsCountedRef
219 * A class that creates (adds) a new reference to a resource on construction
220 * or assignment and releases on destruction.
222 * This class is similar to nsAutoRef<T> and inherits its methods, but also
223 * provides copy construction and assignment operators that enable more than
224 * one concurrent reference to the same resource.
226 * Specialize |nsAutoRefTraits<T>| or |nsSimpleRef<T>| to use this. This
227 * class assumes that the resource itself counts references and so can only be
228 * used when |T| represents a reference-counting resource.
232 class nsCountedRef
: public nsAutoRef
<T
>
235 typedef nsCountedRef
<T
> ThisClass
;
236 typedef nsAutoRef
<T
> BaseClass
;
237 typedef nsSimpleRef
<T
> SimpleRef
;
238 typedef typename
BaseClass::RawRef RawRef
;
245 // Construction and assignment from a another nsCountedRef
246 // or a raw ref copies and increments the ref count.
247 nsCountedRef(const ThisClass
& aRefToCopy
)
249 SimpleRef::operator=(aRefToCopy
);
252 ThisClass
& operator=(const ThisClass
& aRefToCopy
)
254 if (this == &aRefToCopy
) {
259 SimpleRef::operator=(aRefToCopy
);
264 // Implicit conversion from another smart ref argument (to a raw ref) is
265 // accepted here because construction and assignment safely creates a new
266 // reference without interfering with the reference to copy.
267 explicit nsCountedRef(RawRef aRefToCopy
)
268 : BaseClass(aRefToCopy
)
272 ThisClass
& operator=(RawRef aRefToCopy
)
274 this->own(aRefToCopy
);
279 // Construction and assignment from an nsReturnRef function return value,
280 // which expects to give up ownership, transfers ownership.
281 explicit nsCountedRef(const nsReturningRef
<T
>& aReturning
)
282 : BaseClass(aReturning
)
285 ThisClass
& operator=(const nsReturningRef
<T
>& aReturning
)
287 BaseClass::operator=(aReturning
);
292 // Increase the reference count if there is a resource.
295 if (this->HaveResource()) {
296 this->AddRef(this->get());
302 * template <class T> class nsReturnRef
304 * A type for function return values that hold a reference to a resource that
305 * must be released. See also |nsAutoRef<T>::out()|.
309 class nsReturnRef
: public nsAutoRefBase
<T
>
312 typedef nsAutoRefBase
<T
> BaseClass
;
313 typedef typename
BaseClass::RawRefOnly RawRefOnly
;
316 // For constructing a return value with no resource
321 // For returning a smart reference from a raw reference that must be
322 // released. Explicit construction is required so as not to risk
323 // unintentionally releasing the resource associated with a raw ref.
324 MOZ_IMPLICIT
nsReturnRef(RawRefOnly aRefToRelease
)
325 : BaseClass(aRefToRelease
)
329 // Copy construction transfers ownership
330 nsReturnRef(nsReturnRef
<T
>& aRefToSteal
)
331 : BaseClass(aRefToSteal
)
335 MOZ_IMPLICIT
nsReturnRef(const nsReturningRef
<T
>& aReturning
)
336 : BaseClass(aReturning
)
340 // Conversion to a temporary (const) object referring to this object so
341 // that the reference may be passed from a function return value
342 // (temporary) to another smart reference. There is no need to use this
343 // explicitly. Simply assign a nsReturnRef<T> function return value to a
345 operator nsReturningRef
<T
>()
347 return nsReturningRef
<T
>(*this);
350 // No conversion to RawRef operator is provided on nsReturnRef, to ensure
351 // that the return value is not carelessly assigned to a raw ptr (and the
352 // resource then released). If passing to a function that takes a raw
353 // ptr, use get or disown as appropriate.
357 * template <class T> class nsReturningRef
359 * A class to allow ownership to be transferred from nsReturnRef function
362 * It should not be necessary for clients to reference this
363 * class directly. Simply pass an nsReturnRef<T> to a parameter taking an
364 * |nsReturningRef<T>|.
366 * The conversion operator on nsReturnRef constructs a temporary wrapper of
367 * class nsReturningRef<T> around a non-const reference to the nsReturnRef.
368 * The wrapper can then be passed as an rvalue parameter.
375 friend class nsReturnRef
<T
>;
377 explicit nsReturningRef(nsReturnRef
<T
>& aReturnRef
)
378 : mReturnRef(aReturnRef
)
382 nsReturnRef
<T
>& mReturnRef
;
386 * template <class T> class nsAutoRefTraits
388 * A class describing traits of references managed by the default
389 * |nsSimpleRef<T>| implementation and thus |nsAutoRef<T>| and |nsCountedRef|.
390 * The default |nsSimpleRef<T> is suitable for resources with handles that
391 * have a void value. (If there is no such void value for a handle,
392 * specialize |nsSimpleRef<T>|.)
394 * Specializations must be provided for each class |T| according to the
397 * // The template parameter |T| should be a class such that the set of fields
398 * // in class nsAutoRefTraits<T> is unique for class |T|. Usually the
399 * // resource object class is sufficient. For handles that are simple
400 * // integral typedefs, a new unique possibly-incomplete class may need to be
404 * class nsAutoRefTraits<T>
406 * // Specializations must provide a typedef for RawRef, describing the
407 * // type of the handle to the resource.
408 * typedef <handle-type> RawRef;
410 * // Specializations should define Void(), a function returning a value
411 * // suitable for a handle that does not have an associated resource.
413 * // The return type must be a suitable as the parameter to a RawRef
414 * // constructor and operator==.
416 * // If this method is not accessible then some limited nsAutoRef
417 * // functionality will still be available, but the default constructor,
418 * // |reset|, and most transfer of ownership methods will not be available.
419 * static <return-type> Void();
421 * // Specializations must define Release() to properly finalize the
422 * // handle to a non-void custom-deleted or reference-counted resource.
423 * static void Release(RawRef aRawRef);
425 * // For reference-counted resources, if |nsCountedRef<T>| is to be used,
426 * // specializations must define AddRef to increment the reference count
427 * // held by a non-void handle.
428 * // (AddRef() is not necessary for |nsAutoRef<T>|.)
429 * static void AddRef(RawRef aRawRef);
432 * See nsPointerRefTraits for example specializations for simple pointer
433 * references. See nsAutoRef for an example specialization for a non-pointer
437 template <class T
> class nsAutoRefTraits
;
440 * template <class T> class nsPointerRefTraits
442 * A convenience class useful as a base class for specializations of
443 * |nsAutoRefTraits<T>| where the handle to the resource is a pointer to |T|.
444 * By inheriting from this class, definitions of only Release(RawRef) and
445 * possibly AddRef(RawRef) need to be added.
450 * class nsAutoRefTraits<PRFileDesc> : public nsPointerRefTraits<PRFileDesc>
453 * static void Release(PRFileDesc *ptr) { PR_Close(ptr); }
457 * class nsAutoRefTraits<FcPattern> : public nsPointerRefTraits<FcPattern>
460 * static void Release(FcPattern *ptr) { FcPatternDestroy(ptr); }
461 * static void AddRef(FcPattern *ptr) { FcPatternReference(ptr); }
466 class nsPointerRefTraits
469 // The handle is a pointer to T.
471 // A nullptr does not have a resource.
479 * template <class T> class nsSimpleRef
481 * Constructs a non-smart reference, and provides methods to test whether
482 * there is an associated resource and (if so) get its raw handle.
484 * A default implementation is suitable for resources with handles that have a
485 * void value. This is not intended for direct use but used by |nsAutoRef<T>|
486 * and thus |nsCountedRef<T>|.
488 * Specialize this class if there is no particular void value for the resource
489 * handle. A specialized implementation must also provide Release(RawRef),
490 * and, if |nsCountedRef<T>| is required, AddRef(RawRef), as described in
491 * nsAutoRefTraits<T>.
495 class nsSimpleRef
: protected nsAutoRefTraits
<T
>
498 // The default implementation uses nsAutoRefTrait<T>.
499 // Specializations need not define this typedef.
500 typedef nsAutoRefTraits
<T
> Traits
;
501 // The type of the handle to the resource.
502 // A specialization must provide a typedef for RawRef.
503 typedef typename
Traits::RawRef RawRef
;
505 // Construct with no resource.
507 // If this constructor is not accessible then some limited nsAutoRef
508 // functionality will still be available, but the default constructor,
509 // |reset|, and most transfer of ownership methods will not be available.
511 : mRawRef(Traits::Void())
514 // Construct with a handle to a resource.
515 // A specialization must provide this.
516 explicit nsSimpleRef(RawRef aRawRef
)
521 // Test whether there is an associated resource. A specialization must
522 // provide this. The function is permitted to always return true if the
523 // default constructor is not accessible, or if Release (and AddRef) can
524 // deal with void handles.
525 bool HaveResource() const
527 return mRawRef
!= Traits::Void();
531 // A specialization must provide get() or loose some functionality. This
532 // is inherited by derived classes and the specialization may choose
533 // whether it is public or protected.
545 * template <class T> class nsAutoRefBase
547 * Internal base class for |nsAutoRef<T>| and |nsReturnRef<T>|.
548 * Adds release on destruction to a |nsSimpleRef<T>|.
552 class nsAutoRefBase
: public nsSimpleRef
<T
>
555 typedef nsAutoRefBase
<T
> ThisClass
;
556 typedef nsSimpleRef
<T
> SimpleRef
;
557 typedef typename
SimpleRef::RawRef RawRef
;
563 // A type for parameters that should be passed a raw ref but should not
564 // accept implicit conversions (from another smart ref). (The only
565 // conversion to this type is from a raw ref so only raw refs will be
570 MOZ_IMPLICIT
RawRefOnly(RawRef aRawRef
)
574 operator RawRef() const
582 // Construction from a raw ref assumes ownership
583 explicit nsAutoRefBase(RawRefOnly aRefToRelease
)
584 : SimpleRef(aRefToRelease
)
588 // Constructors that steal ownership
589 explicit nsAutoRefBase(ThisClass
& aRefToSteal
)
590 : SimpleRef(aRefToSteal
.disown())
593 explicit nsAutoRefBase(const nsReturningRef
<T
>& aReturning
)
594 : SimpleRef(aReturning
.mReturnRef
.disown())
603 // An internal class providing access to protected nsSimpleRef<T>
604 // constructors for construction of temporary simple references (that are
606 class LocalSimpleRef
: public SimpleRef
612 explicit LocalSimpleRef(RawRef aRawRef
)
619 ThisClass
& operator=(const ThisClass
& aSmartRef
) = delete;
622 RawRef
operator->() const
627 // Transfer ownership to a raw reference.
629 // THE CALLER MUST ENSURE THAT THE REFERENCE IS EXPLICITLY RELEASED.
631 // Is this really what you want to use? Using this removes any guarantee
632 // of release. Use nsAutoRef<T>::out() for return values, or an
633 // nsAutoRef<T> modifiable lvalue for an out parameter. Use disown() when
634 // the reference must be stored in a POD type object, such as may be
635 // preferred for a namespace-scope object with static storage duration,
639 RawRef temp
= this->get();
640 LocalSimpleRef empty
;
641 SimpleRef::operator=(empty
);
646 // steal and own are protected because they make no sense on nsReturnRef,
647 // but steal is implemented on this class for access to aOtherRef.disown()
648 // when aOtherRef is an nsReturnRef;
650 // Transfer ownership from another smart reference.
651 void steal(ThisClass
& aOtherRef
)
653 own(aOtherRef
.disown());
655 // Assume ownership of a raw ref.
656 void own(RawRefOnly aRefToRelease
)
659 LocalSimpleRef
ref(aRefToRelease
);
660 SimpleRef::operator=(ref
);
663 // Release a resource if there is one.
666 if (this->HaveResource()) {
667 this->Release(this->get());
672 #endif // !defined(nsAutoRef_h_)