Bug 575870 - Enable the firefox button on xp themed, classic, and aero basic. r=dao...
[mozilla-central.git] / xpcom / base / nsAutoRef.h
blobb8f09ecc6a7f56ea8f258f66fe0425993e65008b
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
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/
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.
16 * The Original Code is mozilla.org code.
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.
23 * Contributor(s):
24 * Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
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.
38 * ***** END LICENSE BLOCK ***** */
40 #ifndef nsAutoRef_h_
41 #define nsAutoRef_h_
43 #include "nscore.h" // for nsnull, PRBool
45 template <class T> class nsSimpleRef;
46 template <class T> class nsAutoRefBase;
47 template <class T> class nsReturnRef;
48 template <class T> class nsReturningRef;
50 /**
51 * template <class T> class nsAutoRef
53 * A class that holds a handle to a resource that must be released.
54 * No reference is added on construction.
56 * No copy constructor nor copy assignment operators are available, so the
57 * resource will be held until released on destruction or explicitly
58 * |reset()| or transferred through provided methods.
60 * The publicly available methods are the public methods on this class and its
61 * public base classes |nsAutoRefBase<T>| and |nsSimpleRef<T>|.
63 * For ref-counted resources see also |nsCountedRef<T>|.
64 * For function return values see |nsReturnRef<T>|.
66 * For each class |T|, |nsAutoRefTraits<T>| or |nsSimpleRef<T>| must be
67 * specialized to use |nsAutoRef<T>| and |nsCountedRef<T>|.
69 * @param T A class identifying the type of reference held by the
70 * |nsAutoRef<T>| and the unique set methods for managing references
71 * to the resource (defined by |nsAutoRefTraits<T>| or
72 * |nsSimpleRef<T>|).
74 * Often this is the class representing the resource. Sometimes a
75 * new possibly-incomplete class may need to be declared.
78 * Example: An Automatically closing file descriptor
80 * // References that are simple integral types (as file-descriptors are)
81 * // usually need a new class to represent the resource and how to handle its
82 * // references.
83 * class nsRawFD;
85 * // Specializing nsAutoRefTraits<nsRawFD> describes how to manage file
86 * // descriptors, so that nsAutoRef<nsRawFD> provides automatic closing of
87 * // its file descriptor on destruction.
88 * NS_SPECIALIZE_TEMPLATE
89 * class nsAutoRefTraits<nsRawFD> {
90 * public:
91 * // The file descriptor is held in an int.
92 * typedef int RawRef;
93 * // -1 means that there is no file associated with the handle.
94 * static int Void() { return -1; }
95 * // The file associated with a file descriptor is released with close().
96 * static void Release(RawRef aFD) { close(aFD); }
97 * };
99 * // A function returning a file descriptor that must be closed.
100 * nsReturnRef<nsRawFD> get_file(const char *filename) {
101 * // Constructing from a raw file descriptor assumes ownership.
102 * nsAutoRef<nsRawFD> fd(open(filename, O_RDONLY));
103 * fcntl(fd, F_SETFD, FD_CLOEXEC);
104 * return fd.out();
107 * void f() {
108 * unsigned char buf[1024];
110 * // Hold a file descriptor for /etc/hosts in fd1.
111 * nsAutoRef<nsRawFD> fd1(get_file("/etc/hosts"));
113 * nsAutoRef<nsRawFD> fd2;
114 * fd2.steal(fd1); // fd2 takes the file descriptor from fd1
115 * ssize_t count = read(fd1, buf, 1024); // error fd1 has no file
116 * count = read(fd2, buf, 1024); // reads from /etc/hosts
118 * // If the file descriptor is not stored then it is closed.
119 * get_file("/etc/login.defs"); // login.defs is closed
121 * // Now use fd1 to hold a file descriptor for /etc/passwd.
122 * fd1 = get_file("/etc/passwd");
124 * // The nsAutoRef<nsRawFD> can give up the file descriptor if explicitly
125 * // instructed, but the caller must then ensure that the file is closed.
126 * int rawfd = fd1.disown();
128 * // Assume ownership of another file descriptor.
129 * fd1.own(open("/proc/1/maps");
131 * // On destruction, fd1 closes /proc/1/maps and fd2 closes /etc/hosts,
132 * // but /etc/passwd is not closed.
138 template <class T>
139 class nsAutoRef : public nsAutoRefBase<T>
141 protected:
142 typedef nsAutoRef<T> ThisClass;
143 typedef nsAutoRefBase<T> BaseClass;
144 typedef nsSimpleRef<T> SimpleRef;
145 typedef typename BaseClass::RawRefOnly RawRefOnly;
146 typedef typename BaseClass::LocalSimpleRef LocalSimpleRef;
148 public:
149 nsAutoRef()
153 // Explicit construction is required so as not to risk unintentionally
154 // releasing the resource associated with a raw ref.
155 explicit nsAutoRef(RawRefOnly aRefToRelease)
156 : BaseClass(aRefToRelease)
160 // Construction from a nsReturnRef<T> function return value, which expects
161 // to give up ownership, transfers ownership.
162 // (nsReturnRef<T> is converted to const nsReturningRef<T>.)
163 explicit nsAutoRef(const nsReturningRef<T>& aReturning)
164 : BaseClass(aReturning)
168 // The only assignment operator provided is for transferring from an
169 // nsReturnRef smart reference, which expects to pass its ownership to
170 // another object.
172 // With raw references and other smart references, the type of the lhs and
173 // its taking and releasing nature is often not obvious from an assignment
174 // statement. Assignment from a raw ptr especially is not normally
175 // expected to release the reference.
177 // Use |steal| for taking ownership from other smart refs.
179 // For raw references, use |own| to indicate intention to have the
180 // resource released.
182 // Or, to create another owner of the same reference, use an nsCountedRef.
184 ThisClass& operator=(const nsReturningRef<T>& aReturning)
186 BaseClass::steal(aReturning.mReturnRef);
187 return *this;
190 // Conversion to a raw reference allow the nsAutoRef<T> to often be used
191 // like a raw reference.
192 operator typename SimpleRef::RawRef() const
194 return this->get();
197 // Transfer ownership from another smart reference.
198 void steal(ThisClass& aOtherRef)
200 BaseClass::steal(aOtherRef);
203 // Assume ownership of a raw ref.
205 // |own| has similar function to |steal|, and is useful for receiving
206 // ownership from a return value of a function. It is named differently
207 // because |own| requires more care to ensure that the function intends to
208 // give away ownership, and so that |steal| can be safely used, knowing
209 // that it won't steal ownership from any methods returning raw ptrs to
210 // data owned by a foreign object.
211 void own(RawRefOnly aRefToRelease)
213 BaseClass::own(aRefToRelease);
216 // Exchange ownership with |aOther|
217 void swap(ThisClass& aOther)
219 LocalSimpleRef temp;
220 temp.SimpleRef::operator=(this);
221 SimpleRef::operator=(aOther);
222 aOther.SimpleRef::operator=(temp);
225 // Release the reference now.
226 void reset()
228 this->SafeRelease();
229 LocalSimpleRef empty;
230 SimpleRef::operator=(empty);
233 // Pass out the reference for a function return values.
234 nsReturnRef<T> out()
236 return nsReturnRef<T>(this->disown());
239 // operator->() and disown() are provided by nsAutoRefBase<T>.
240 // The default nsSimpleRef<T> provides get().
242 private:
243 // No copy constructor
244 explicit nsAutoRef(ThisClass& aRefToSteal);
248 * template <class T> class nsCountedRef
250 * A class that creates (adds) a new reference to a resource on construction
251 * or assignment and releases on destruction.
253 * This class is similar to nsAutoRef<T> and inherits its methods, but also
254 * provides copy construction and assignment operators that enable more than
255 * one concurrent reference to the same resource.
257 * Specialize |nsAutoRefTraits<T>| or |nsSimpleRef<T>| to use this. This
258 * class assumes that the resource itself counts references and so can only be
259 * used when |T| represents a reference-counting resource.
262 template <class T>
263 class nsCountedRef : public nsAutoRef<T>
265 protected:
266 typedef nsCountedRef<T> ThisClass;
267 typedef nsAutoRef<T> BaseClass;
268 typedef nsSimpleRef<T> SimpleRef;
269 typedef typename BaseClass::RawRef RawRef;
271 public:
272 nsCountedRef()
276 // Construction and assignment from a another nsCountedRef
277 // or a raw ref copies and increments the ref count.
278 nsCountedRef(const ThisClass& aRefToCopy)
280 SimpleRef::operator=(aRefToCopy);
281 SafeAddRef();
283 ThisClass& operator=(const ThisClass& aRefToCopy)
285 if (this == &aRefToCopy)
286 return *this;
288 this->SafeRelease();
289 SimpleRef::operator=(aRefToCopy);
290 SafeAddRef();
291 return *this;
294 // Implicit conversion from another smart ref argument (to a raw ref) is
295 // accepted here because construction and assignment safely creates a new
296 // reference without interfering with the reference to copy.
297 explicit nsCountedRef(RawRef aRefToCopy)
298 : BaseClass(aRefToCopy)
300 SafeAddRef();
302 ThisClass& operator=(RawRef aRefToCopy)
304 this->own(aRefToCopy);
305 SafeAddRef();
306 return *this;
309 // Construction and assignment from an nsReturnRef function return value,
310 // which expects to give up ownership, transfers ownership.
311 explicit nsCountedRef(const nsReturningRef<T>& aReturning)
312 : BaseClass(aReturning)
315 ThisClass& operator=(const nsReturningRef<T>& aReturning)
317 BaseClass::operator=(aReturning);
318 return *this;
321 protected:
322 // Increase the reference count if there is a resource.
323 void SafeAddRef()
325 if (this->HaveResource())
326 this->AddRef(this->get());
331 * template <class T> class nsReturnRef
333 * A type for function return values that hold a reference to a resource that
334 * must be released. See also |nsAutoRef<T>::out()|.
337 template <class T>
338 class nsReturnRef : public nsAutoRefBase<T>
340 protected:
341 typedef nsAutoRefBase<T> BaseClass;
342 typedef typename BaseClass::RawRefOnly RawRefOnly;
344 public:
345 // For constructing a return value with no resource
346 nsReturnRef()
350 // For returning a smart reference from a raw reference that must be
351 // released. Explicit construction is required so as not to risk
352 // unintentionally releasing the resource associated with a raw ref.
353 explicit nsReturnRef(RawRefOnly aRefToRelease)
354 : BaseClass(aRefToRelease)
358 // Copy construction transfers ownership
359 nsReturnRef(nsReturnRef<T>& aRefToSteal)
360 : BaseClass(aRefToSteal)
364 nsReturnRef(const nsReturningRef<T>& aReturning)
365 : BaseClass(aReturning)
369 // Conversion to a temporary (const) object referring to this object so
370 // that the reference may be passed from a function return value
371 // (temporary) to another smart reference. There is no need to use this
372 // explicitly. Simply assign a nsReturnRef<T> function return value to a
373 // smart reference.
374 operator nsReturningRef<T>()
376 return nsReturningRef<T>(*this);
379 // No conversion to RawRef operator is provided on nsReturnRef, to ensure
380 // that the return value is not carelessly assigned to a raw ptr (and the
381 // resource then released). If passing to a function that takes a raw
382 // ptr, use get or disown as appropriate.
386 * template <class T> class nsReturningRef
388 * A class to allow ownership to be transferred from nsReturnRef function
389 * return values.
391 * It should not be necessary for clients to reference this
392 * class directly. Simply pass an nsReturnRef<T> to a parameter taking an
393 * |nsReturningRef<T>|.
395 * The conversion operator on nsReturnRef constructs a temporary wrapper of
396 * class nsReturningRef<T> around a non-const reference to the nsReturnRef.
397 * The wrapper can then be passed as an rvalue parameter.
400 template <class T>
401 class nsReturningRef
403 private:
404 friend class nsReturnRef<T>;
406 explicit nsReturningRef(nsReturnRef<T>& aReturnRef)
407 : mReturnRef(aReturnRef)
410 public:
411 nsReturnRef<T>& mReturnRef;
415 * template <class T> class nsAutoRefTraits
417 * A class describing traits of references managed by the default
418 * |nsSimpleRef<T>| implementation and thus |nsAutoRef<T>| and |nsCountedRef|.
419 * The default |nsSimpleRef<T> is suitable for resources with handles that
420 * have a void value. (If there is no such void value for a handle,
421 * specialize |nsSimpleRef<T>|.)
423 * Specializations must be provided for each class |T| according to the
424 * following pattern:
426 * // The template parameter |T| should be a class such that the set of fields
427 * // in class nsAutoRefTraits<T> is unique for class |T|. Usually the
428 * // resource object class is sufficient. For handles that are simple
429 * // integral typedefs, a new unique possibly-incomplete class may need to be
430 * // declared.
432 * NS_SPECIALIZE_TEMPLATE
433 * class nsAutoRefTraits<T>
435 * // Specializations must provide a typedef for RawRef, describing the
436 * // type of the handle to the resource.
437 * typedef <handle-type> RawRef;
439 * // Specializations should define Void(), a function returning a value
440 * // suitable for a handle that does not have an associated resource.
441 * //
442 * // The return type must be a suitable as the parameter to a RawRef
443 * // constructor and operator==.
444 * //
445 * // If this method is not accessible then some limited nsAutoRef
446 * // functionality will still be available, but the default constructor,
447 * // |reset|, and most transfer of ownership methods will not be available.
448 * static <return-type> Void();
450 * // Specializations must define Release() to properly finalize the
451 * // handle to a non-void custom-deleted or reference-counted resource.
452 * static void Release(RawRef aRawRef);
454 * // For reference-counted resources, if |nsCountedRef<T>| is to be used,
455 * // specializations must define AddRef to increment the reference count
456 * // held by a non-void handle.
457 * // (AddRef() is not necessary for |nsAutoRef<T>|.)
458 * static void AddRef(RawRef aRawRef);
459 * };
461 * See nsPointerRefTraits for example specializations for simple pointer
462 * references. See nsAutoRef for an example specialization for a non-pointer
463 * reference.
466 template <class T> class nsAutoRefTraits;
469 * template <class T> class nsPointerRefTraits
471 * A convenience class useful as a base class for specializations of
472 * |nsAutoRefTraits<T>| where the handle to the resource is a pointer to |T|.
473 * By inheriting from this class, definitions of only Release(RawRef) and
474 * possibly AddRef(RawRef) need to be added.
476 * Examples of use:
478 * NS_SPECIALIZE_TEMPLATE
479 * class nsAutoRefTraits<PRFileDesc> : public nsPointerRefTraits<PRFileDesc>
481 * public:
482 * static void Release(PRFileDesc *ptr) { PR_Close(ptr); }
483 * };
485 * NS_SPECIALIZE_TEMPLATE
486 * class nsAutoRefTraits<FcPattern> : public nsPointerRefTraits<FcPattern>
488 * public:
489 * static void Release(FcPattern *ptr) { FcPatternDestroy(ptr); }
490 * static void AddRef(FcPattern *ptr) { FcPatternReference(ptr); }
491 * };
494 template <class T>
495 class nsPointerRefTraits
497 public:
498 // The handle is a pointer to T.
499 typedef T* RawRef;
500 // A NULL pointer does not have a resource.
501 static RawRef Void() { return nsnull; };
505 * template <class T> class nsSimpleRef
507 * Constructs a non-smart reference, and provides methods to test whether
508 * there is an associated resource and (if so) get its raw handle.
510 * A default implementation is suitable for resources with handles that have a
511 * void value. This is not intended for direct use but used by |nsAutoRef<T>|
512 * and thus |nsCountedRef<T>|.
514 * Specialize this class if there is no particular void value for the resource
515 * handle. A specialized implementation must also provide Release(RawRef),
516 * and, if |nsCountedRef<T>| is required, AddRef(RawRef), as described in
517 * nsAutoRefTraits<T>.
520 template <class T>
521 class nsSimpleRef : protected nsAutoRefTraits<T>
523 protected:
524 // The default implementation uses nsAutoRefTrait<T>.
525 // Specializations need not define this typedef.
526 typedef nsAutoRefTraits<T> Traits;
527 // The type of the handle to the resource.
528 // A specialization must provide a typedef for RawRef.
529 typedef typename Traits::RawRef RawRef;
531 // Construct with no resource.
533 // If this constructor is not accessible then some limited nsAutoRef
534 // functionality will still be available, but the default constructor,
535 // |reset|, and most transfer of ownership methods will not be available.
536 nsSimpleRef()
537 : mRawRef(Traits::Void())
540 // Construct with a handle to a resource.
541 // A specialization must provide this.
542 nsSimpleRef(RawRef aRawRef)
543 : mRawRef(aRawRef)
547 // Test whether there is an associated resource. A specialization must
548 // provide this. The function is permitted to always return true if the
549 // default constructor is not accessible, or if Release (and AddRef) can
550 // deal with void handles.
551 PRBool HaveResource() const
553 return mRawRef != Traits::Void();
556 public:
557 // A specialization must provide get() or loose some functionality. This
558 // is inherited by derived classes and the specialization may choose
559 // whether it is public or protected.
560 RawRef get() const
562 return mRawRef;
565 private:
566 RawRef mRawRef;
571 * template <class T> class nsAutoRefBase
573 * Internal base class for |nsAutoRef<T>| and |nsReturnRef<T>|.
574 * Adds release on destruction to a |nsSimpleRef<T>|.
577 template <class T>
578 class nsAutoRefBase : public nsSimpleRef<T>
580 protected:
581 typedef nsAutoRefBase<T> ThisClass;
582 typedef nsSimpleRef<T> SimpleRef;
583 typedef typename SimpleRef::RawRef RawRef;
585 nsAutoRefBase()
589 // A type for parameters that should be passed a raw ref but should not
590 // accept implicit conversions (from another smart ref). (The only
591 // conversion to this type is from a raw ref so only raw refs will be
592 // accepted.)
593 class RawRefOnly
595 public:
596 RawRefOnly(RawRef aRawRef)
597 : mRawRef(aRawRef)
600 operator RawRef() const
602 return mRawRef;
604 private:
605 RawRef mRawRef;
608 // Construction from a raw ref assumes ownership
609 explicit nsAutoRefBase(RawRefOnly aRefToRelease)
610 : SimpleRef(aRefToRelease)
614 // Constructors that steal ownership
615 explicit nsAutoRefBase(ThisClass& aRefToSteal)
616 : SimpleRef(aRefToSteal.disown())
619 explicit nsAutoRefBase(const nsReturningRef<T>& aReturning)
620 : SimpleRef(aReturning.mReturnRef.disown())
624 ~nsAutoRefBase()
626 SafeRelease();
629 // An internal class providing access to protected nsSimpleRef<T>
630 // constructors for construction of temporary simple references (that are
631 // not ThisClass).
632 class LocalSimpleRef : public SimpleRef
634 public:
635 LocalSimpleRef()
638 explicit LocalSimpleRef(RawRef aRawRef)
639 : SimpleRef(aRawRef)
644 private:
645 ThisClass& operator=(const ThisClass& aSmartRef);
647 public:
648 RawRef operator->() const
650 return this->get();
653 // Transfer ownership to a raw reference.
655 // THE CALLER MUST ENSURE THAT THE REFERENCE IS EXPLICITLY RELEASED.
657 // Is this really what you want to use? Using this removes any guarantee
658 // of release. Use nsAutoRef<T>::out() for return values, or an
659 // nsAutoRef<T> modifiable lvalue for an out parameter. Use disown() when
660 // the reference must be stored in a POD type object, such as may be
661 // preferred for a namespace-scope object with static storage duration,
662 // for example.
663 RawRef disown()
665 RawRef temp = this->get();
666 LocalSimpleRef empty;
667 SimpleRef::operator=(empty);
668 return temp;
671 protected:
672 // steal and own are protected because they make no sense on nsReturnRef,
673 // but steal is implemented on this class for access to aOtherRef.disown()
674 // when aOtherRef is an nsReturnRef;
676 // Transfer ownership from another smart reference.
677 void steal(ThisClass& aOtherRef)
679 own(aOtherRef.disown());
681 // Assume ownership of a raw ref.
682 void own(RawRefOnly aRefToRelease)
684 SafeRelease();
685 LocalSimpleRef ref(aRefToRelease);
686 SimpleRef::operator=(ref);
689 // Release a resource if there is one.
690 void SafeRelease()
692 if (this->HaveResource())
693 this->Release(this->get());
697 #endif // !defined(nsAutoRef_h_)