blob: 0df15beac5778ea4df878bf04a2b44f9ff46d388 [file] [log] [blame]
andrew@webrtc.orga3c6d612011-09-13 17:17:49 +00001// 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_