xpcom/base/nsAutoRef.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial