1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
3 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * The Mozilla Foundation.
20 : * Portions created by the Initial Developer are Copyright (C) 2008
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #ifndef nsAutoRef_h_
41 : #define nsAutoRef_h_
42 :
43 : #include "mozilla/Attributes.h"
44 :
45 : #include "nscore.h" // for nsnull, bool
46 :
47 : template <class T> class nsSimpleRef;
48 : template <class T> class nsAutoRefBase;
49 : template <class T> class nsReturnRef;
50 : template <class T> class nsReturningRef;
51 :
52 : /**
53 : * template <class T> class nsAutoRef
54 : *
55 : * A class that holds a handle to a resource that must be released.
56 : * No reference is added on construction.
57 : *
58 : * No copy constructor nor copy assignment operators are available, so the
59 : * resource will be held until released on destruction or explicitly
60 : * |reset()| or transferred through provided methods.
61 : *
62 : * The publicly available methods are the public methods on this class and its
63 : * public base classes |nsAutoRefBase<T>| and |nsSimpleRef<T>|.
64 : *
65 : * For ref-counted resources see also |nsCountedRef<T>|.
66 : * For function return values see |nsReturnRef<T>|.
67 : *
68 : * For each class |T|, |nsAutoRefTraits<T>| or |nsSimpleRef<T>| must be
69 : * specialized to use |nsAutoRef<T>| and |nsCountedRef<T>|.
70 : *
71 : * @param T A class identifying the type of reference held by the
72 : * |nsAutoRef<T>| and the unique set methods for managing references
73 : * to the resource (defined by |nsAutoRefTraits<T>| or
74 : * |nsSimpleRef<T>|).
75 : *
76 : * Often this is the class representing the resource. Sometimes a
77 : * new possibly-incomplete class may need to be declared.
78 : *
79 : *
80 : * Example: An Automatically closing file descriptor
81 : *
82 : * // References that are simple integral types (as file-descriptors are)
83 : * // usually need a new class to represent the resource and how to handle its
84 : * // references.
85 : * class nsRawFD;
86 : *
87 : * // Specializing nsAutoRefTraits<nsRawFD> describes how to manage file
88 : * // descriptors, so that nsAutoRef<nsRawFD> provides automatic closing of
89 : * // its file descriptor on destruction.
90 : * template <>
91 : * class nsAutoRefTraits<nsRawFD> {
92 : * public:
93 : * // The file descriptor is held in an int.
94 : * typedef int RawRef;
95 : * // -1 means that there is no file associated with the handle.
96 : * static int Void() { return -1; }
97 : * // The file associated with a file descriptor is released with close().
98 : * static void Release(RawRef aFD) { close(aFD); }
99 : * };
100 : *
101 : * // A function returning a file descriptor that must be closed.
102 : * nsReturnRef<nsRawFD> get_file(const char *filename) {
103 : * // Constructing from a raw file descriptor assumes ownership.
104 : * nsAutoRef<nsRawFD> fd(open(filename, O_RDONLY));
105 : * fcntl(fd, F_SETFD, FD_CLOEXEC);
106 : * return fd.out();
107 : * }
108 : *
109 : * void f() {
110 : * unsigned char buf[1024];
111 : *
112 : * // Hold a file descriptor for /etc/hosts in fd1.
113 : * nsAutoRef<nsRawFD> fd1(get_file("/etc/hosts"));
114 : *
115 : * nsAutoRef<nsRawFD> fd2;
116 : * fd2.steal(fd1); // fd2 takes the file descriptor from fd1
117 : * ssize_t count = read(fd1, buf, 1024); // error fd1 has no file
118 : * count = read(fd2, buf, 1024); // reads from /etc/hosts
119 : *
120 : * // If the file descriptor is not stored then it is closed.
121 : * get_file("/etc/login.defs"); // login.defs is closed
122 : *
123 : * // Now use fd1 to hold a file descriptor for /etc/passwd.
124 : * fd1 = get_file("/etc/passwd");
125 : *
126 : * // The nsAutoRef<nsRawFD> can give up the file descriptor if explicitly
127 : * // instructed, but the caller must then ensure that the file is closed.
128 : * int rawfd = fd1.disown();
129 : *
130 : * // Assume ownership of another file descriptor.
131 : * fd1.own(open("/proc/1/maps");
132 : *
133 : * // On destruction, fd1 closes /proc/1/maps and fd2 closes /etc/hosts,
134 : * // but /etc/passwd is not closed.
135 : * }
136 : *
137 : */
138 :
139 :
140 : template <class T>
141 : class nsAutoRef : public nsAutoRefBase<T>
142 429 : {
143 : protected:
144 : typedef nsAutoRef<T> ThisClass;
145 : typedef nsAutoRefBase<T> BaseClass;
146 : typedef nsSimpleRef<T> SimpleRef;
147 : typedef typename BaseClass::RawRefOnly RawRefOnly;
148 : typedef typename BaseClass::LocalSimpleRef LocalSimpleRef;
149 :
150 : public:
151 0 : nsAutoRef()
152 0 : {
153 0 : }
154 :
155 : // Explicit construction is required so as not to risk unintentionally
156 : // releasing the resource associated with a raw ref.
157 429 : explicit nsAutoRef(RawRefOnly aRefToRelease)
158 429 : : BaseClass(aRefToRelease)
159 : {
160 429 : }
161 :
162 : // Construction from a nsReturnRef<T> function return value, which expects
163 : // to give up ownership, transfers ownership.
164 : // (nsReturnRef<T> is converted to const nsReturningRef<T>.)
165 0 : explicit nsAutoRef(const nsReturningRef<T>& aReturning)
166 0 : : BaseClass(aReturning)
167 : {
168 0 : }
169 :
170 : // The only assignment operator provided is for transferring from an
171 : // nsReturnRef smart reference, which expects to pass its ownership to
172 : // another object.
173 : //
174 : // With raw references and other smart references, the type of the lhs and
175 : // its taking and releasing nature is often not obvious from an assignment
176 : // statement. Assignment from a raw ptr especially is not normally
177 : // expected to release the reference.
178 : //
179 : // Use |steal| for taking ownership from other smart refs.
180 : //
181 : // For raw references, use |own| to indicate intention to have the
182 : // resource released.
183 : //
184 : // Or, to create another owner of the same reference, use an nsCountedRef.
185 :
186 0 : ThisClass& operator=(const nsReturningRef<T>& aReturning)
187 : {
188 0 : BaseClass::steal(aReturning.mReturnRef);
189 0 : return *this;
190 : }
191 :
192 : // Conversion to a raw reference allow the nsAutoRef<T> to often be used
193 : // like a raw reference.
194 0 : operator typename SimpleRef::RawRef() const
195 : {
196 0 : return this->get();
197 : }
198 :
199 : // Transfer ownership from another smart reference.
200 0 : void steal(ThisClass& aOtherRef)
201 : {
202 0 : BaseClass::steal(aOtherRef);
203 0 : }
204 :
205 : // Assume ownership of a raw ref.
206 : //
207 : // |own| has similar function to |steal|, and is useful for receiving
208 : // ownership from a return value of a function. It is named differently
209 : // because |own| requires more care to ensure that the function intends to
210 : // give away ownership, and so that |steal| can be safely used, knowing
211 : // that it won't steal ownership from any methods returning raw ptrs to
212 : // data owned by a foreign object.
213 0 : void own(RawRefOnly aRefToRelease)
214 : {
215 0 : BaseClass::own(aRefToRelease);
216 0 : }
217 :
218 : // Exchange ownership with |aOther|
219 : void swap(ThisClass& aOther)
220 : {
221 : LocalSimpleRef temp;
222 : temp.SimpleRef::operator=(this);
223 : SimpleRef::operator=(aOther);
224 : aOther.SimpleRef::operator=(temp);
225 : }
226 :
227 : // Release the reference now.
228 0 : void reset()
229 : {
230 0 : this->SafeRelease();
231 0 : LocalSimpleRef empty;
232 0 : SimpleRef::operator=(empty);
233 0 : }
234 :
235 : // Pass out the reference for a function return values.
236 0 : nsReturnRef<T> out()
237 : {
238 0 : return nsReturnRef<T>(this->disown());
239 : }
240 :
241 : // operator->() and disown() are provided by nsAutoRefBase<T>.
242 : // The default nsSimpleRef<T> provides get().
243 :
244 : private:
245 : // No copy constructor
246 : explicit nsAutoRef(ThisClass& aRefToSteal);
247 : };
248 :
249 : /**
250 : * template <class T> class nsCountedRef
251 : *
252 : * A class that creates (adds) a new reference to a resource on construction
253 : * or assignment and releases on destruction.
254 : *
255 : * This class is similar to nsAutoRef<T> and inherits its methods, but also
256 : * provides copy construction and assignment operators that enable more than
257 : * one concurrent reference to the same resource.
258 : *
259 : * Specialize |nsAutoRefTraits<T>| or |nsSimpleRef<T>| to use this. This
260 : * class assumes that the resource itself counts references and so can only be
261 : * used when |T| represents a reference-counting resource.
262 : */
263 :
264 : template <class T>
265 : class nsCountedRef : public nsAutoRef<T>
266 429 : {
267 : protected:
268 : typedef nsCountedRef<T> ThisClass;
269 : typedef nsAutoRef<T> BaseClass;
270 : typedef nsSimpleRef<T> SimpleRef;
271 : typedef typename BaseClass::RawRef RawRef;
272 :
273 : public:
274 0 : nsCountedRef()
275 0 : {
276 0 : }
277 :
278 : // Construction and assignment from a another nsCountedRef
279 : // or a raw ref copies and increments the ref count.
280 0 : nsCountedRef(const ThisClass& aRefToCopy)
281 0 : {
282 0 : SimpleRef::operator=(aRefToCopy);
283 0 : SafeAddRef();
284 0 : }
285 : ThisClass& operator=(const ThisClass& aRefToCopy)
286 : {
287 : if (this == &aRefToCopy)
288 : return *this;
289 :
290 : this->SafeRelease();
291 : SimpleRef::operator=(aRefToCopy);
292 : SafeAddRef();
293 : return *this;
294 : }
295 :
296 : // Implicit conversion from another smart ref argument (to a raw ref) is
297 : // accepted here because construction and assignment safely creates a new
298 : // reference without interfering with the reference to copy.
299 429 : explicit nsCountedRef(RawRef aRefToCopy)
300 429 : : BaseClass(aRefToCopy)
301 : {
302 429 : SafeAddRef();
303 429 : }
304 0 : ThisClass& operator=(RawRef aRefToCopy)
305 : {
306 0 : this->own(aRefToCopy);
307 0 : SafeAddRef();
308 0 : return *this;
309 : }
310 :
311 : // Construction and assignment from an nsReturnRef function return value,
312 : // which expects to give up ownership, transfers ownership.
313 : explicit nsCountedRef(const nsReturningRef<T>& aReturning)
314 : : BaseClass(aReturning)
315 : {
316 : }
317 : ThisClass& operator=(const nsReturningRef<T>& aReturning)
318 : {
319 : BaseClass::operator=(aReturning);
320 : return *this;
321 : }
322 :
323 : protected:
324 : // Increase the reference count if there is a resource.
325 429 : void SafeAddRef()
326 : {
327 429 : if (this->HaveResource())
328 429 : this->AddRef(this->get());
329 429 : }
330 : };
331 :
332 : /**
333 : * template <class T> class nsReturnRef
334 : *
335 : * A type for function return values that hold a reference to a resource that
336 : * must be released. See also |nsAutoRef<T>::out()|.
337 : */
338 :
339 : template <class T>
340 : class nsReturnRef : public nsAutoRefBase<T>
341 0 : {
342 : protected:
343 : typedef nsAutoRefBase<T> BaseClass;
344 : typedef typename BaseClass::RawRefOnly RawRefOnly;
345 :
346 : public:
347 : // For constructing a return value with no resource
348 0 : nsReturnRef()
349 0 : {
350 0 : }
351 :
352 : // For returning a smart reference from a raw reference that must be
353 : // released. Explicit construction is required so as not to risk
354 : // unintentionally releasing the resource associated with a raw ref.
355 0 : explicit nsReturnRef(RawRefOnly aRefToRelease)
356 0 : : BaseClass(aRefToRelease)
357 : {
358 0 : }
359 :
360 : // Copy construction transfers ownership
361 : nsReturnRef(nsReturnRef<T>& aRefToSteal)
362 : : BaseClass(aRefToSteal)
363 : {
364 : }
365 :
366 0 : nsReturnRef(const nsReturningRef<T>& aReturning)
367 0 : : BaseClass(aReturning)
368 : {
369 0 : }
370 :
371 : // Conversion to a temporary (const) object referring to this object so
372 : // that the reference may be passed from a function return value
373 : // (temporary) to another smart reference. There is no need to use this
374 : // explicitly. Simply assign a nsReturnRef<T> function return value to a
375 : // smart reference.
376 0 : operator nsReturningRef<T>()
377 : {
378 0 : return nsReturningRef<T>(*this);
379 : }
380 :
381 : // No conversion to RawRef operator is provided on nsReturnRef, to ensure
382 : // that the return value is not carelessly assigned to a raw ptr (and the
383 : // resource then released). If passing to a function that takes a raw
384 : // ptr, use get or disown as appropriate.
385 : };
386 :
387 : /**
388 : * template <class T> class nsReturningRef
389 : *
390 : * A class to allow ownership to be transferred from nsReturnRef function
391 : * return values.
392 : *
393 : * It should not be necessary for clients to reference this
394 : * class directly. Simply pass an nsReturnRef<T> to a parameter taking an
395 : * |nsReturningRef<T>|.
396 : *
397 : * The conversion operator on nsReturnRef constructs a temporary wrapper of
398 : * class nsReturningRef<T> around a non-const reference to the nsReturnRef.
399 : * The wrapper can then be passed as an rvalue parameter.
400 : */
401 :
402 : template <class T>
403 : class nsReturningRef
404 : {
405 : private:
406 : friend class nsReturnRef<T>;
407 :
408 0 : explicit nsReturningRef(nsReturnRef<T>& aReturnRef)
409 0 : : mReturnRef(aReturnRef)
410 : {
411 0 : }
412 : public:
413 : nsReturnRef<T>& mReturnRef;
414 : };
415 :
416 : /**
417 : * template <class T> class nsAutoRefTraits
418 : *
419 : * A class describing traits of references managed by the default
420 : * |nsSimpleRef<T>| implementation and thus |nsAutoRef<T>| and |nsCountedRef|.
421 : * The default |nsSimpleRef<T> is suitable for resources with handles that
422 : * have a void value. (If there is no such void value for a handle,
423 : * specialize |nsSimpleRef<T>|.)
424 : *
425 : * Specializations must be provided for each class |T| according to the
426 : * following pattern:
427 : *
428 : * // The template parameter |T| should be a class such that the set of fields
429 : * // in class nsAutoRefTraits<T> is unique for class |T|. Usually the
430 : * // resource object class is sufficient. For handles that are simple
431 : * // integral typedefs, a new unique possibly-incomplete class may need to be
432 : * // declared.
433 : *
434 : * template <>
435 : * class nsAutoRefTraits<T>
436 : * {
437 : * // Specializations must provide a typedef for RawRef, describing the
438 : * // type of the handle to the resource.
439 : * typedef <handle-type> RawRef;
440 : *
441 : * // Specializations should define Void(), a function returning a value
442 : * // suitable for a handle that does not have an associated resource.
443 : * //
444 : * // The return type must be a suitable as the parameter to a RawRef
445 : * // constructor and operator==.
446 : * //
447 : * // If this method is not accessible then some limited nsAutoRef
448 : * // functionality will still be available, but the default constructor,
449 : * // |reset|, and most transfer of ownership methods will not be available.
450 : * static <return-type> Void();
451 : *
452 : * // Specializations must define Release() to properly finalize the
453 : * // handle to a non-void custom-deleted or reference-counted resource.
454 : * static void Release(RawRef aRawRef);
455 : *
456 : * // For reference-counted resources, if |nsCountedRef<T>| is to be used,
457 : * // specializations must define AddRef to increment the reference count
458 : * // held by a non-void handle.
459 : * // (AddRef() is not necessary for |nsAutoRef<T>|.)
460 : * static void AddRef(RawRef aRawRef);
461 : * };
462 : *
463 : * See nsPointerRefTraits for example specializations for simple pointer
464 : * references. See nsAutoRef for an example specialization for a non-pointer
465 : * reference.
466 : */
467 :
468 : template <class T> class nsAutoRefTraits;
469 :
470 : /**
471 : * template <class T> class nsPointerRefTraits
472 : *
473 : * A convenience class useful as a base class for specializations of
474 : * |nsAutoRefTraits<T>| where the handle to the resource is a pointer to |T|.
475 : * By inheriting from this class, definitions of only Release(RawRef) and
476 : * possibly AddRef(RawRef) need to be added.
477 : *
478 : * Examples of use:
479 : *
480 : * template <>
481 : * class nsAutoRefTraits<PRFileDesc> : public nsPointerRefTraits<PRFileDesc>
482 : * {
483 : * public:
484 : * static void Release(PRFileDesc *ptr) { PR_Close(ptr); }
485 : * };
486 : *
487 : * template <>
488 : * class nsAutoRefTraits<FcPattern> : public nsPointerRefTraits<FcPattern>
489 : * {
490 : * public:
491 : * static void Release(FcPattern *ptr) { FcPatternDestroy(ptr); }
492 : * static void AddRef(FcPattern *ptr) { FcPatternReference(ptr); }
493 : * };
494 : */
495 :
496 : template <class T>
497 : class nsPointerRefTraits
498 429 : {
499 : public:
500 : // The handle is a pointer to T.
501 : typedef T* RawRef;
502 : // A NULL pointer does not have a resource.
503 858 : static RawRef Void() { return nsnull; };
504 : };
505 :
506 : /**
507 : * template <class T> class nsSimpleRef
508 : *
509 : * Constructs a non-smart reference, and provides methods to test whether
510 : * there is an associated resource and (if so) get its raw handle.
511 : *
512 : * A default implementation is suitable for resources with handles that have a
513 : * void value. This is not intended for direct use but used by |nsAutoRef<T>|
514 : * and thus |nsCountedRef<T>|.
515 : *
516 : * Specialize this class if there is no particular void value for the resource
517 : * handle. A specialized implementation must also provide Release(RawRef),
518 : * and, if |nsCountedRef<T>| is required, AddRef(RawRef), as described in
519 : * nsAutoRefTraits<T>.
520 : */
521 :
522 : template <class T>
523 : class nsSimpleRef : protected nsAutoRefTraits<T>
524 : {
525 : protected:
526 : // The default implementation uses nsAutoRefTrait<T>.
527 : // Specializations need not define this typedef.
528 : typedef nsAutoRefTraits<T> Traits;
529 : // The type of the handle to the resource.
530 : // A specialization must provide a typedef for RawRef.
531 : typedef typename Traits::RawRef RawRef;
532 :
533 : // Construct with no resource.
534 : //
535 : // If this constructor is not accessible then some limited nsAutoRef
536 : // functionality will still be available, but the default constructor,
537 : // |reset|, and most transfer of ownership methods will not be available.
538 0 : nsSimpleRef()
539 0 : : mRawRef(Traits::Void())
540 : {
541 0 : }
542 : // Construct with a handle to a resource.
543 : // A specialization must provide this.
544 429 : nsSimpleRef(RawRef aRawRef)
545 429 : : mRawRef(aRawRef)
546 : {
547 429 : }
548 :
549 : // Test whether there is an associated resource. A specialization must
550 : // provide this. The function is permitted to always return true if the
551 : // default constructor is not accessible, or if Release (and AddRef) can
552 : // deal with void handles.
553 858 : bool HaveResource() const
554 : {
555 858 : return mRawRef != Traits::Void();
556 : }
557 :
558 : public:
559 : // A specialization must provide get() or loose some functionality. This
560 : // is inherited by derived classes and the specialization may choose
561 : // whether it is public or protected.
562 858 : RawRef get() const
563 : {
564 858 : return mRawRef;
565 : }
566 :
567 : private:
568 : RawRef mRawRef;
569 : };
570 :
571 :
572 : /**
573 : * template <class T> class nsAutoRefBase
574 : *
575 : * Internal base class for |nsAutoRef<T>| and |nsReturnRef<T>|.
576 : * Adds release on destruction to a |nsSimpleRef<T>|.
577 : */
578 :
579 : template <class T>
580 : class nsAutoRefBase : public nsSimpleRef<T>
581 : {
582 : protected:
583 : typedef nsAutoRefBase<T> ThisClass;
584 : typedef nsSimpleRef<T> SimpleRef;
585 : typedef typename SimpleRef::RawRef RawRef;
586 :
587 0 : nsAutoRefBase()
588 0 : {
589 0 : }
590 :
591 : // A type for parameters that should be passed a raw ref but should not
592 : // accept implicit conversions (from another smart ref). (The only
593 : // conversion to this type is from a raw ref so only raw refs will be
594 : // accepted.)
595 : class RawRefOnly
596 : {
597 : public:
598 429 : RawRefOnly(RawRef aRawRef)
599 429 : : mRawRef(aRawRef)
600 : {
601 429 : }
602 429 : operator RawRef() const
603 : {
604 429 : return mRawRef;
605 : }
606 : private:
607 : RawRef mRawRef;
608 : };
609 :
610 : // Construction from a raw ref assumes ownership
611 429 : explicit nsAutoRefBase(RawRefOnly aRefToRelease)
612 429 : : SimpleRef(aRefToRelease)
613 : {
614 429 : }
615 :
616 : // Constructors that steal ownership
617 : explicit nsAutoRefBase(ThisClass& aRefToSteal)
618 : : SimpleRef(aRefToSteal.disown())
619 : {
620 : }
621 0 : explicit nsAutoRefBase(const nsReturningRef<T>& aReturning)
622 0 : : SimpleRef(aReturning.mReturnRef.disown())
623 : {
624 0 : }
625 :
626 429 : ~nsAutoRefBase()
627 : {
628 429 : SafeRelease();
629 429 : }
630 :
631 : // An internal class providing access to protected nsSimpleRef<T>
632 : // constructors for construction of temporary simple references (that are
633 : // not ThisClass).
634 : class LocalSimpleRef : public SimpleRef
635 : {
636 : public:
637 0 : LocalSimpleRef()
638 0 : {
639 0 : }
640 0 : explicit LocalSimpleRef(RawRef aRawRef)
641 0 : : SimpleRef(aRawRef)
642 : {
643 0 : }
644 : };
645 :
646 : private:
647 : ThisClass& operator=(const ThisClass& aSmartRef) MOZ_DELETE;
648 :
649 : public:
650 0 : RawRef operator->() const
651 : {
652 0 : return this->get();
653 : }
654 :
655 : // Transfer ownership to a raw reference.
656 : //
657 : // THE CALLER MUST ENSURE THAT THE REFERENCE IS EXPLICITLY RELEASED.
658 : //
659 : // Is this really what you want to use? Using this removes any guarantee
660 : // of release. Use nsAutoRef<T>::out() for return values, or an
661 : // nsAutoRef<T> modifiable lvalue for an out parameter. Use disown() when
662 : // the reference must be stored in a POD type object, such as may be
663 : // preferred for a namespace-scope object with static storage duration,
664 : // for example.
665 0 : RawRef disown()
666 : {
667 0 : RawRef temp = this->get();
668 0 : LocalSimpleRef empty;
669 0 : SimpleRef::operator=(empty);
670 0 : return temp;
671 : }
672 :
673 : protected:
674 : // steal and own are protected because they make no sense on nsReturnRef,
675 : // but steal is implemented on this class for access to aOtherRef.disown()
676 : // when aOtherRef is an nsReturnRef;
677 :
678 : // Transfer ownership from another smart reference.
679 0 : void steal(ThisClass& aOtherRef)
680 : {
681 0 : own(aOtherRef.disown());
682 0 : }
683 : // Assume ownership of a raw ref.
684 0 : void own(RawRefOnly aRefToRelease)
685 : {
686 0 : SafeRelease();
687 0 : LocalSimpleRef ref(aRefToRelease);
688 0 : SimpleRef::operator=(ref);
689 0 : }
690 :
691 : // Release a resource if there is one.
692 429 : void SafeRelease()
693 : {
694 429 : if (this->HaveResource())
695 429 : this->Release(this->get());
696 429 : }
697 : };
698 :
699 : #endif // !defined(nsAutoRef_h_)
|