1// Copyright (c) 2011 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 under third_party_mods/chromium or at:
4// http://src.chromium.org/svn/trunk/src/LICENSE
5
6#ifndef SYSTEM_WRAPPERS_INTERFACE_SCOPED_REFPTR_H_
7#define SYSTEM_WRAPPERS_INTERFACE_SCOPED_REFPTR_H_
8
9namespace webrtc {
10
11// Extracted from Chromium's src/base/memory/ref_counted.h.
12
13//
14// A smart pointer class for reference counted objects.  Use this class instead
15// of calling AddRef and Release manually on a reference counted object to
16// avoid common memory leaks caused by forgetting to Release an object
17// reference.  Sample usage:
18//
19//   class MyFoo : public RefCounted<MyFoo> {
20//    ...
21//   };
22//
23//   void some_function() {
24//     scoped_refptr<MyFoo> foo = new MyFoo();
25//     foo->Method(param);
26//     // |foo| is released when this function returns
27//   }
28//
29//   void some_other_function() {
30//     scoped_refptr<MyFoo> foo = new MyFoo();
31//     ...
32//     foo = NULL;  // explicitly releases |foo|
33//     ...
34//     if (foo)
35//       foo->Method(param);
36//   }
37//
38// The above examples show how scoped_refptr<T> acts like a pointer to T.
39// Given two scoped_refptr<T> classes, it is also possible to exchange
40// references between the two objects, like so:
41//
42//   {
43//     scoped_refptr<MyFoo> a = new MyFoo();
44//     scoped_refptr<MyFoo> b;
45//
46//     b.swap(a);
47//     // now, |b| references the MyFoo object, and |a| references NULL.
48//   }
49//
50// To make both |a| and |b| in the above example reference the same MyFoo
51// object, simply use the assignment operator:
52//
53//   {
54//     scoped_refptr<MyFoo> a = new MyFoo();
55//     scoped_refptr<MyFoo> b;
56//
57//     b = a;
58//     // now, |a| and |b| each own a reference to the same MyFoo object.
59//   }
60//
61template <class T>
62class scoped_refptr {
63 public:
64  scoped_refptr() : ptr_(NULL) {
65  }
66
67  scoped_refptr(T* p) : ptr_(p) {
68    if (ptr_)
69      ptr_->AddRef();
70  }
71
72  scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
73    if (ptr_)
74      ptr_->AddRef();
75  }
76
77  template <typename U>
78  scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
79    if (ptr_)
80      ptr_->AddRef();
81  }
82
83  ~scoped_refptr() {
84    if (ptr_)
85      ptr_->Release();
86  }
87
88  T* get() const { return ptr_; }
89  operator T*() const { return ptr_; }
90  T* operator->() const { return ptr_; }
91
92  // Release a pointer.
93  // The return value is the current pointer held by this object.
94  // If this object holds a NULL pointer, the return value is NULL.
95  // After this operation, this object will hold a NULL pointer,
96  // and will not own the object any more.
97  T* release() {
98    T* retVal = ptr_;
99    ptr_ = NULL;
100    return retVal;
101  }
102
103  scoped_refptr<T>& operator=(T* p) {
104    // AddRef first so that self assignment should work
105    if (p)
106      p->AddRef();
107    if (ptr_ )
108      ptr_->Release();
109    ptr_ = p;
110    return *this;
111  }
112
113  scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
114    return *this = r.ptr_;
115  }
116
117  template <typename U>
118  scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
119    return *this = r.get();
120  }
121
122  void swap(T** pp) {
123    T* p = ptr_;
124    ptr_ = *pp;
125    *pp = p;
126  }
127
128  void swap(scoped_refptr<T>& r) {
129    swap(&r.ptr_);
130  }
131
132 protected:
133  T* ptr_;
134};
135}  // namespace webrtc
136
137#endif  // SYSTEM_WRAPPERS_INTERFACE_SCOPED_REFPTR_H_
138