blob: 3ce72cbce6d47b75fd8be7e9d0fb05b091b73cfd [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2011, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28// Originally these classes are from Chromium.
29// http://src.chromium.org/viewvc/chrome/trunk/src/base/memory/ref_counted.h?view=markup
30
31//
32// A smart pointer class for reference counted objects. Use this class instead
33// of calling AddRef and Release manually on a reference counted object to
34// avoid common memory leaks caused by forgetting to Release an object
35// reference. Sample usage:
36//
37// class MyFoo : public RefCounted<MyFoo> {
38// ...
39// };
40//
41// void some_function() {
42// scoped_refptr<MyFoo> foo = new MyFoo();
43// foo->Method(param);
44// // |foo| is released when this function returns
45// }
46//
47// void some_other_function() {
48// scoped_refptr<MyFoo> foo = new MyFoo();
49// ...
50// foo = NULL; // explicitly releases |foo|
51// ...
52// if (foo)
53// foo->Method(param);
54// }
55//
56// The above examples show how scoped_refptr<T> acts like a pointer to T.
57// Given two scoped_refptr<T> classes, it is also possible to exchange
58// references between the two objects, like so:
59//
60// {
61// scoped_refptr<MyFoo> a = new MyFoo();
62// scoped_refptr<MyFoo> b;
63//
64// b.swap(a);
65// // now, |b| references the MyFoo object, and |a| references NULL.
66// }
67//
68// To make both |a| and |b| in the above example reference the same MyFoo
69// object, simply use the assignment operator:
70//
71// {
72// scoped_refptr<MyFoo> a = new MyFoo();
73// scoped_refptr<MyFoo> b;
74//
75// b = a;
76// // now, |a| and |b| each own a reference to the same MyFoo object.
77// }
78//
79
80#ifndef TALK_BASE_SCOPED_REF_PTR_H_
81#define TALK_BASE_SCOPED_REF_PTR_H_
82
83namespace talk_base {
84
85template <class T>
86class scoped_refptr {
87 public:
88 scoped_refptr() : ptr_(NULL) {
89 }
90
91 scoped_refptr(T* p) : ptr_(p) {
92 if (ptr_)
93 ptr_->AddRef();
94 }
95
96 scoped_refptr(const scoped_refptr<T>& r) : ptr_(r.ptr_) {
97 if (ptr_)
98 ptr_->AddRef();
99 }
100
101 template <typename U>
102 scoped_refptr(const scoped_refptr<U>& r) : ptr_(r.get()) {
103 if (ptr_)
104 ptr_->AddRef();
105 }
106
107 ~scoped_refptr() {
108 if (ptr_)
109 ptr_->Release();
110 }
111
112 T* get() const { return ptr_; }
113 operator T*() const { return ptr_; }
114 T* operator->() const { return ptr_; }
115
116 // Release a pointer.
117 // The return value is the current pointer held by this object.
118 // If this object holds a NULL pointer, the return value is NULL.
119 // After this operation, this object will hold a NULL pointer,
120 // and will not own the object any more.
121 T* release() {
122 T* retVal = ptr_;
123 ptr_ = NULL;
124 return retVal;
125 }
126
127 scoped_refptr<T>& operator=(T* p) {
128 // AddRef first so that self assignment should work
129 if (p)
130 p->AddRef();
131 if (ptr_ )
132 ptr_ ->Release();
133 ptr_ = p;
134 return *this;
135 }
136
137 scoped_refptr<T>& operator=(const scoped_refptr<T>& r) {
138 return *this = r.ptr_;
139 }
140
141 template <typename U>
142 scoped_refptr<T>& operator=(const scoped_refptr<U>& r) {
143 return *this = r.get();
144 }
145
146 void swap(T** pp) {
147 T* p = ptr_;
148 ptr_ = *pp;
149 *pp = p;
150 }
151
152 void swap(scoped_refptr<T>& r) {
153 swap(&r.ptr_);
154 }
155
156 protected:
157 T* ptr_;
158};
159
160} // namespace talk_base
161
162#endif // TALK_BASE_SCOPED_REF_PTR_H_