ipc/chromium/src/base/linked_ptr.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.

     1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
     2 // Use of this source code is governed by a BSD-style license that can be
     3 // found in the LICENSE file.
     4 //
     5 // A "smart" pointer type with reference tracking.  Every pointer to a
     6 // particular object is kept on a circular linked list.  When the last pointer
     7 // to an object is destroyed or reassigned, the object is deleted.
     8 //
     9 // Used properly, this deletes the object when the last reference goes away.
    10 // There are several caveats:
    11 // - Like all reference counting schemes, cycles lead to leaks.
    12 // - Each smart pointer is actually two pointers (8 bytes instead of 4).
    13 // - Every time a pointer is released, the entire list of pointers to that
    14 //   object is traversed.  This class is therefore NOT SUITABLE when there
    15 //   will often be more than two or three pointers to a particular object.
    16 // - References are only tracked as long as linked_ptr<> objects are copied.
    17 //   If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS
    18 //   will happen (double deletion).
    19 //
    20 // A good use of this class is storing object references in STL containers.
    21 // You can safely put linked_ptr<> in a vector<>.
    22 // Other uses may not be as good.
    23 //
    24 // Note: If you use an incomplete type with linked_ptr<>, the class
    25 // *containing* linked_ptr<> must have a constructor and destructor (even
    26 // if they do nothing!).
    27 //
    28 // Thread Safety:
    29 //   A linked_ptr is NOT thread safe. Copying a linked_ptr object is
    30 //   effectively a read-write operation.
    31 //
    32 // Alternative: to linked_ptr is shared_ptr, which
    33 //  - is also two pointers in size (8 bytes for 32 bit addresses)
    34 //  - is thread safe for copying and deletion
    35 //  - supports weak_ptrs
    37 #ifndef BASE_LINKED_PTR_H_
    38 #define BASE_LINKED_PTR_H_
    40 #include "base/logging.h"  // for CHECK macros
    42 // This is used internally by all instances of linked_ptr<>.  It needs to be
    43 // a non-template class because different types of linked_ptr<> can refer to
    44 // the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)).
    45 // So, it needs to be possible for different types of linked_ptr to participate
    46 // in the same circular linked list, so we need a single class type here.
    47 //
    48 // DO NOT USE THIS CLASS DIRECTLY YOURSELF.  Use linked_ptr<T>.
    49 class linked_ptr_internal {
    50  public:
    51   // Create a new circle that includes only this instance.
    52   void join_new() {
    53     next_ = this;
    54   }
    56   // Join an existing circle.
    57   void join(linked_ptr_internal const* ptr) {
    58     next_ = ptr->next_;
    59     ptr->next_ = this;
    60   }
    62   // Leave whatever circle we're part of.  Returns true iff we were the
    63   // last member of the circle.  Once this is done, you can join() another.
    64   bool depart() {
    65     if (next_ == this) return true;
    66     linked_ptr_internal const* p = next_;
    67     while (p->next_ != this) p = p->next_;
    68     p->next_ = next_;
    69     return false;
    70   }
    72  private:
    73   mutable linked_ptr_internal const* next_;
    74 };
    76 template <typename T>
    77 class linked_ptr {
    78  public:
    79   typedef T element_type;
    81   // Take over ownership of a raw pointer.  This should happen as soon as
    82   // possible after the object is created.
    83   explicit linked_ptr(T* ptr = NULL) { capture(ptr); }
    84   ~linked_ptr() { depart(); }
    86   // Copy an existing linked_ptr<>, adding ourselves to the list of references.
    87   template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); }
    88   linked_ptr(linked_ptr const& ptr) { DCHECK_NE(&ptr, this); copy(&ptr); }
    90   // Assignment releases the old value and acquires the new.
    91   template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) {
    92     depart();
    93     copy(&ptr);
    94     return *this;
    95   }
    97   linked_ptr& operator=(linked_ptr const& ptr) {
    98     if (&ptr != this) {
    99       depart();
   100       copy(&ptr);
   101     }
   102     return *this;
   103   }
   105   // Smart pointer members.
   106   void reset(T* ptr = NULL) { depart(); capture(ptr); }
   107   T* get() const { return value_; }
   108   T* operator->() const { return value_; }
   109   T& operator*() const { return *value_; }
   110   // Release ownership of the pointed object and returns it.
   111   // Sole ownership by this linked_ptr object is required.
   112   T* release() {
   113     bool last = link_.depart();
   114     CHECK(last);
   115     T* v = value_;
   116     value_ = NULL;
   117     return v;
   118   }
   120   bool operator==(const T* p) const { return value_ == p; }
   121   bool operator!=(const T* p) const { return value_ != p; }
   122   template <typename U>
   123   bool operator==(linked_ptr<U> const& ptr) const {
   124     return value_ == ptr.get();
   125   }
   126   template <typename U>
   127   bool operator!=(linked_ptr<U> const& ptr) const {
   128     return value_ != ptr.get();
   129   }
   131  private:
   132   template <typename U>
   133   friend class linked_ptr;
   135   T* value_;
   136   linked_ptr_internal link_;
   138   void depart() {
   139     if (link_.depart()) delete value_;
   140   }
   142   void capture(T* ptr) {
   143     value_ = ptr;
   144     link_.join_new();
   145   }
   147   template <typename U> void copy(linked_ptr<U> const* ptr) {
   148     value_ = ptr->get();
   149     if (value_)
   150       link_.join(&ptr->link_);
   151     else
   152       link_.join_new();
   153   }
   154 };
   156 template<typename T> inline
   157 bool operator==(T* ptr, const linked_ptr<T>& x) {
   158   return ptr == x.get();
   159 }
   161 template<typename T> inline
   162 bool operator!=(T* ptr, const linked_ptr<T>& x) {
   163   return ptr != x.get();
   164 }
   166 // A function to convert T* into linked_ptr<T>
   167 // Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation
   168 // for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
   169 template <typename T>
   170 linked_ptr<T> make_linked_ptr(T* ptr) {
   171   return linked_ptr<T>(ptr);
   172 }
   174 #endif  // BASE_LINKED_PTR_H_

mercurial