Bug 1686838 [wpt PR 27194] - [webcodecs] Deprecate VideoFrame.destroy()., a=testonly
[gecko.git] / xpcom / base / nsAutoRef.h
blob1a9c214a4ab6b703bac1c49267b79f028e67935d
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/. */
7 // NB: This code may be used from non-XPCOM code, in particular, the
8 // Windows Default Browser Agent.
10 #ifndef nsAutoRef_h_
11 #define nsAutoRef_h_
13 #include "mozilla/Attributes.h"
15 template <class T>
16 class nsSimpleRef;
17 template <class T>
18 class nsAutoRefBase;
19 template <class T>
20 class nsReturnRef;
21 template <class T>
22 class nsReturningRef;
24 /**
25 * template <class T> class nsAutoRef
27 * A class that holds a handle to a resource that must be released.
28 * No reference is added on construction.
30 * No copy constructor nor copy assignment operators are available, so the
31 * resource will be held until released on destruction or explicitly
32 * |reset()| or transferred through provided methods.
34 * The publicly available methods are the public methods on this class and its
35 * public base classes |nsAutoRefBase<T>| and |nsSimpleRef<T>|.
37 * For function return values see |nsReturnRef<T>|.
39 * For each class |T|, |nsAutoRefTraits<T>| or |nsSimpleRef<T>| must be
40 * specialized to use |nsAutoRef<T>|.
42 * @param T A class identifying the type of reference held by the
43 * |nsAutoRef<T>| and the unique set methods for managing references
44 * to the resource (defined by |nsAutoRefTraits<T>| or
45 * |nsSimpleRef<T>|).
47 * Often this is the class representing the resource. Sometimes a
48 * new possibly-incomplete class may need to be declared.
51 * Example: An Automatically closing file descriptor
53 * // References that are simple integral types (as file-descriptors are)
54 * // usually need a new class to represent the resource and how to handle its
55 * // references.
56 * class nsRawFD;
58 * // Specializing nsAutoRefTraits<nsRawFD> describes how to manage file
59 * // descriptors, so that nsAutoRef<nsRawFD> provides automatic closing of
60 * // its file descriptor on destruction.
61 * template <>
62 * class nsAutoRefTraits<nsRawFD> {
63 * public:
64 * // The file descriptor is held in an int.
65 * typedef int RawRef;
66 * // -1 means that there is no file associated with the handle.
67 * static int Void() { return -1; }
68 * // The file associated with a file descriptor is released with close().
69 * static void Release(RawRef aFD) { close(aFD); }
70 * };
72 * // A function returning a file descriptor that must be closed.
73 * nsReturnRef<nsRawFD> get_file(const char *filename) {
74 * // Constructing from a raw file descriptor assumes ownership.
75 * nsAutoRef<nsRawFD> fd(open(filename, O_RDONLY));
76 * fcntl(fd, F_SETFD, FD_CLOEXEC);
77 * return fd.out();
78 * }
80 * void f() {
81 * unsigned char buf[1024];
83 * // Hold a file descriptor for /etc/hosts in fd1.
84 * nsAutoRef<nsRawFD> fd1(get_file("/etc/hosts"));
86 * nsAutoRef<nsRawFD> fd2;
87 * fd2.steal(fd1); // fd2 takes the file descriptor from fd1
88 * ssize_t count = read(fd1, buf, 1024); // error fd1 has no file
89 * count = read(fd2, buf, 1024); // reads from /etc/hosts
91 * // If the file descriptor is not stored then it is closed.
92 * get_file("/etc/login.defs"); // login.defs is closed
94 * // Now use fd1 to hold a file descriptor for /etc/passwd.
95 * fd1 = get_file("/etc/passwd");
97 * // The nsAutoRef<nsRawFD> can give up the file descriptor if explicitly
98 * // instructed, but the caller must then ensure that the file is closed.
99 * int rawfd = fd1.disown();
101 * // Assume ownership of another file descriptor.
102 * fd1.own(open("/proc/1/maps");
104 * // On destruction, fd1 closes /proc/1/maps and fd2 closes /etc/hosts,
105 * // but /etc/passwd is not closed.
110 template <class T>
111 class nsAutoRef : public nsAutoRefBase<T> {
112 protected:
113 typedef nsAutoRef<T> ThisClass;
114 typedef nsAutoRefBase<T> BaseClass;
115 typedef nsSimpleRef<T> SimpleRef;
116 typedef typename BaseClass::RawRefOnly RawRefOnly;
117 typedef typename BaseClass::LocalSimpleRef LocalSimpleRef;
119 public:
120 nsAutoRef() = default;
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) : BaseClass(aRefToRelease) {}
126 // Construction from a nsReturnRef<T> function return value, which expects
127 // to give up ownership, transfers ownership.
128 // (nsReturnRef<T> is converted to const nsReturningRef<T>.)
129 explicit nsAutoRef(const nsReturningRef<T>& aReturning)
130 : BaseClass(aReturning) {}
132 // The only assignment operator provided is for transferring from an
133 // nsReturnRef smart reference, which expects to pass its ownership to
134 // another object.
136 // With raw references and other smart references, the type of the lhs and
137 // its taking and releasing nature is often not obvious from an assignment
138 // statement. Assignment from a raw ptr especially is not normally
139 // expected to release the reference.
141 // Use |steal| for taking ownership from other smart refs.
143 // For raw references, use |own| to indicate intention to have the
144 // resource released.
146 ThisClass& operator=(const nsReturningRef<T>& aReturning) {
147 BaseClass::steal(aReturning.mReturnRef);
148 return *this;
151 // Conversion to a raw reference allow the nsAutoRef<T> to often be used
152 // like a raw reference.
153 operator typename SimpleRef::RawRef() const { return this->get(); }
155 explicit operator bool() const { return this->HaveResource(); }
157 // Transfer ownership from another smart reference.
158 void steal(ThisClass& aOtherRef) { BaseClass::steal(aOtherRef); }
160 // Assume ownership of a raw ref.
162 // |own| has similar function to |steal|, and is useful for receiving
163 // ownership from a return value of a function. It is named differently
164 // because |own| requires more care to ensure that the function intends to
165 // give away ownership, and so that |steal| can be safely used, knowing
166 // that it won't steal ownership from any methods returning raw ptrs to
167 // data owned by a foreign object.
168 void own(RawRefOnly aRefToRelease) { BaseClass::own(aRefToRelease); }
170 // Exchange ownership with |aOther|
171 void swap(ThisClass& aOther) {
172 LocalSimpleRef temp;
173 temp.SimpleRef::operator=(*this);
174 SimpleRef::operator=(aOther);
175 aOther.SimpleRef::operator=(temp);
178 // Release the reference now.
179 void reset() {
180 this->SafeRelease();
181 LocalSimpleRef empty;
182 SimpleRef::operator=(empty);
185 // Pass out the reference for a function return values.
186 nsReturnRef<T> out() { return nsReturnRef<T>(this->disown()); }
188 // operator->() and disown() are provided by nsAutoRefBase<T>.
189 // The default nsSimpleRef<T> provides get().
191 private:
192 // No copy constructor
193 explicit nsAutoRef(ThisClass& aRefToSteal);
197 * template <class T> class nsReturnRef
199 * A type for function return values that hold a reference to a resource that
200 * must be released. See also |nsAutoRef<T>::out()|.
203 template <class T>
204 class nsReturnRef : public nsAutoRefBase<T> {
205 protected:
206 typedef nsAutoRefBase<T> BaseClass;
207 typedef typename BaseClass::RawRefOnly RawRefOnly;
209 public:
210 // For constructing a return value with no resource
211 nsReturnRef() = default;
213 // For returning a smart reference from a raw reference that must be
214 // released. Explicit construction is required so as not to risk
215 // unintentionally releasing the resource associated with a raw ref.
216 MOZ_IMPLICIT nsReturnRef(RawRefOnly aRefToRelease)
217 : BaseClass(aRefToRelease) {}
219 // Copy construction transfers ownership
220 nsReturnRef(nsReturnRef<T>& aRefToSteal) : BaseClass(aRefToSteal) {}
222 MOZ_IMPLICIT nsReturnRef(const nsReturningRef<T>& aReturning)
223 : BaseClass(aReturning) {}
225 // Conversion to a temporary (const) object referring to this object so
226 // that the reference may be passed from a function return value
227 // (temporary) to another smart reference. There is no need to use this
228 // explicitly. Simply assign a nsReturnRef<T> function return value to a
229 // smart reference.
230 operator nsReturningRef<T>() { return nsReturningRef<T>(*this); }
232 // No conversion to RawRef operator is provided on nsReturnRef, to ensure
233 // that the return value is not carelessly assigned to a raw ptr (and the
234 // resource then released). If passing to a function that takes a raw
235 // ptr, use get or disown as appropriate.
239 * template <class T> class nsReturningRef
241 * A class to allow ownership to be transferred from nsReturnRef function
242 * return values.
244 * It should not be necessary for clients to reference this
245 * class directly. Simply pass an nsReturnRef<T> to a parameter taking an
246 * |nsReturningRef<T>|.
248 * The conversion operator on nsReturnRef constructs a temporary wrapper of
249 * class nsReturningRef<T> around a non-const reference to the nsReturnRef.
250 * The wrapper can then be passed as an rvalue parameter.
253 template <class T>
254 class nsReturningRef {
255 private:
256 friend class nsReturnRef<T>;
258 explicit nsReturningRef(nsReturnRef<T>& aReturnRef)
259 : mReturnRef(aReturnRef) {}
261 public:
262 nsReturnRef<T>& mReturnRef;
266 * template <class T> class nsAutoRefTraits
268 * A class describing traits of references managed by the default
269 * |nsSimpleRef<T>| implementation and thus |nsAutoRef<T>|.
270 * The default |nsSimpleRef<T> is suitable for resources with handles that
271 * have a void value. (If there is no such void value for a handle,
272 * specialize |nsSimpleRef<T>|.)
274 * Specializations must be provided for each class |T| according to the
275 * following pattern:
277 * // The template parameter |T| should be a class such that the set of fields
278 * // in class nsAutoRefTraits<T> is unique for class |T|. Usually the
279 * // resource object class is sufficient. For handles that are simple
280 * // integral typedefs, a new unique possibly-incomplete class may need to be
281 * // declared.
283 * template <>
284 * class nsAutoRefTraits<T>
286 * // Specializations must provide a typedef for RawRef, describing the
287 * // type of the handle to the resource.
288 * typedef <handle-type> RawRef;
290 * // Specializations should define Void(), a function returning a value
291 * // suitable for a handle that does not have an associated resource.
292 * //
293 * // The return type must be a suitable as the parameter to a RawRef
294 * // constructor and operator==.
295 * //
296 * // If this method is not accessible then some limited nsAutoRef
297 * // functionality will still be available, but the default constructor,
298 * // |reset|, and most transfer of ownership methods will not be available.
299 * static <return-type> Void();
301 * // Specializations must define Release() to properly finalize the
302 * // handle to a non-void custom-deleted or reference-counted resource.
303 * static void Release(RawRef aRawRef);
304 * };
306 * See nsPointerRefTraits for example specializations for simple pointer
307 * references. See nsAutoRef for an example specialization for a non-pointer
308 * reference.
311 template <class T>
312 class nsAutoRefTraits;
315 * template <class T> class nsPointerRefTraits
317 * A convenience class useful as a base class for specializations of
318 * |nsAutoRefTraits<T>| where the handle to the resource is a pointer to |T|.
319 * By inheriting from this class, definitions of only Release(RawRef) and
320 * possibly AddRef(RawRef) need to be added.
322 * Examples of use:
324 * template <>
325 * class nsAutoRefTraits<PRFileDesc> : public nsPointerRefTraits<PRFileDesc>
327 * public:
328 * static void Release(PRFileDesc *ptr) { PR_Close(ptr); }
329 * };
331 * template <>
332 * class nsAutoRefTraits<FcPattern> : public nsPointerRefTraits<FcPattern>
334 * public:
335 * static void Release(FcPattern *ptr) { FcPatternDestroy(ptr); }
336 * static void AddRef(FcPattern *ptr) { FcPatternReference(ptr); }
337 * };
340 template <class T>
341 class nsPointerRefTraits {
342 public:
343 // The handle is a pointer to T.
344 typedef T* RawRef;
345 // A nullptr does not have a resource.
346 static RawRef Void() { return nullptr; }
350 * template <class T> class nsSimpleRef
352 * Constructs a non-smart reference, and provides methods to test whether
353 * there is an associated resource and (if so) get its raw handle.
355 * A default implementation is suitable for resources with handles that have a
356 * void value. This is not intended for direct use but used by |nsAutoRef<T>|.
358 * Specialize this class if there is no particular void value for the resource
359 * handle. A specialized implementation must also provide Release(RawRef),
362 template <class T>
363 class nsSimpleRef : protected nsAutoRefTraits<T> {
364 protected:
365 // The default implementation uses nsAutoRefTrait<T>.
366 // Specializations need not define this typedef.
367 typedef nsAutoRefTraits<T> Traits;
368 // The type of the handle to the resource.
369 // A specialization must provide a typedef for RawRef.
370 typedef typename Traits::RawRef RawRef;
372 // Construct with no resource.
374 // If this constructor is not accessible then some limited nsAutoRef
375 // functionality will still be available, but the default constructor,
376 // |reset|, and most transfer of ownership methods will not be available.
377 nsSimpleRef() : mRawRef(Traits::Void()) {}
378 // Construct with a handle to a resource.
379 // A specialization must provide this.
380 explicit nsSimpleRef(RawRef aRawRef) : mRawRef(aRawRef) {}
382 // Test whether there is an associated resource. A specialization must
383 // provide this. The function is permitted to always return true if the
384 // default constructor is not accessible, or if Release (and AddRef) can
385 // deal with void handles.
386 bool HaveResource() const { return mRawRef != Traits::Void(); }
388 public:
389 // A specialization must provide get() or loose some functionality. This
390 // is inherited by derived classes and the specialization may choose
391 // whether it is public or protected.
392 RawRef get() const { return mRawRef; }
394 private:
395 RawRef mRawRef;
399 * template <class T> class nsAutoRefBase
401 * Internal base class for |nsAutoRef<T>| and |nsReturnRef<T>|.
402 * Adds release on destruction to a |nsSimpleRef<T>|.
405 template <class T>
406 class nsAutoRefBase : public nsSimpleRef<T> {
407 protected:
408 typedef nsAutoRefBase<T> ThisClass;
409 typedef nsSimpleRef<T> SimpleRef;
410 typedef typename SimpleRef::RawRef RawRef;
412 nsAutoRefBase() = default;
414 // A type for parameters that should be passed a raw ref but should not
415 // accept implicit conversions (from another smart ref). (The only
416 // conversion to this type is from a raw ref so only raw refs will be
417 // accepted.)
418 class RawRefOnly {
419 public:
420 MOZ_IMPLICIT RawRefOnly(RawRef aRawRef) : mRawRef(aRawRef) {}
421 operator RawRef() const { return mRawRef; }
423 private:
424 RawRef mRawRef;
427 // Construction from a raw ref assumes ownership
428 explicit nsAutoRefBase(RawRefOnly aRefToRelease) : SimpleRef(aRefToRelease) {}
430 // Constructors that steal ownership
431 explicit nsAutoRefBase(ThisClass& aRefToSteal)
432 : SimpleRef(aRefToSteal.disown()) {}
433 explicit nsAutoRefBase(const nsReturningRef<T>& aReturning)
434 : SimpleRef(aReturning.mReturnRef.disown()) {}
436 ~nsAutoRefBase() { SafeRelease(); }
438 // An internal class providing access to protected nsSimpleRef<T>
439 // constructors for construction of temporary simple references (that are
440 // not ThisClass).
441 class LocalSimpleRef : public SimpleRef {
442 public:
443 LocalSimpleRef() = default;
444 explicit LocalSimpleRef(RawRef aRawRef) : SimpleRef(aRawRef) {}
447 private:
448 ThisClass& operator=(const ThisClass& aSmartRef) = delete;
450 public:
451 RawRef operator->() const { return this->get(); }
453 // Transfer ownership to a raw reference.
455 // THE CALLER MUST ENSURE THAT THE REFERENCE IS EXPLICITLY RELEASED.
457 // Is this really what you want to use? Using this removes any guarantee
458 // of release. Use nsAutoRef<T>::out() for return values, or an
459 // nsAutoRef<T> modifiable lvalue for an out parameter. Use disown() when
460 // the reference must be stored in a POD type object, such as may be
461 // preferred for a namespace-scope object with static storage duration,
462 // for example.
463 RawRef disown() {
464 RawRef temp = this->get();
465 LocalSimpleRef empty;
466 SimpleRef::operator=(empty);
467 return temp;
470 protected:
471 // steal and own are protected because they make no sense on nsReturnRef,
472 // but steal is implemented on this class for access to aOtherRef.disown()
473 // when aOtherRef is an nsReturnRef;
475 // Transfer ownership from another smart reference.
476 void steal(ThisClass& aOtherRef) { own(aOtherRef.disown()); }
477 // Assume ownership of a raw ref.
478 void own(RawRefOnly aRefToRelease) {
479 SafeRelease();
480 LocalSimpleRef ref(aRefToRelease);
481 SimpleRef::operator=(ref);
484 // Release a resource if there is one.
485 void SafeRelease() {
486 if (this->HaveResource()) {
487 this->Release(this->get());
492 #endif // !defined(nsAutoRef_h_)