1// Copyright 2007 Google Inc.
2// All Rights Reserved.
3//
4//
5#ifndef BASE_SCOPED_PTR_H__
6#define BASE_SCOPED_PTR_H__
7
8// This is an implementation designed to match the anticipated future TR2
9// implementation of the scoped_ptr class, and its closely-related brethren,
10// scoped_array, scoped_ptr_malloc, and make_scoped_ptr.
11//
12// file.
13
14#include <assert.h>
15#include <stdlib.h>
16#include <cstddef>
17
18#ifdef OS_EMBEDDED_QNX
19// NOTE(user):
20// The C++ standard says that <stdlib.h> declares both ::foo and std::foo
21// But this isn't done in QNX version 6.3.2 200709062316.
22using std::free;
23using std::malloc;
24using std::realloc;
25#endif
26
27template <class C> class scoped_ptr;
28template <class C, class Free> class scoped_ptr_malloc;
29template <class C> class scoped_array;
30
31template <class C>
32scoped_ptr<C> make_scoped_ptr(C *);
33
34// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
35// automatically deletes the pointer it holds (if any).
36// That is, scoped_ptr<T> owns the T object that it points to.
37// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
38// Also like T*, scoped_ptr<T> is thread-compatible, and once you
39// dereference it, you get the threadsafety guarantees of T.
40//
41// The size of a scoped_ptr is small:
42// sizeof(scoped_ptr<C>) == sizeof(C*)
43template <class C>
44class scoped_ptr {
45 public:
46
47 // The element type
48 typedef C element_type;
49
50 // Constructor. Defaults to intializing with NULL.
51 // There is no way to create an uninitialized scoped_ptr.
52 // The input parameter must be allocated with new.
53 explicit scoped_ptr(C* p = NULL) : ptr_(p) { }
54
55 // Destructor. If there is a C object, delete it.
56 // We don't need to test ptr_ == NULL because C++ does that for us.
57 ~scoped_ptr() {
58 enum { type_must_be_complete = sizeof(C) };
59 delete ptr_;
60 }
61
62 // Reset. Deletes the current owned object, if any.
63 // Then takes ownership of a new object, if given.
64 // this->reset(this->get()) works.
65 void reset(C* p = NULL) {
66 if (p != ptr_) {
67 enum { type_must_be_complete = sizeof(C) };
68 delete ptr_;
69 ptr_ = p;
70 }
71 }
72
73 // Accessors to get the owned object.
74 // operator* and operator-> will assert() if there is no current object.
75 C& operator*() const {
76 assert(ptr_ != NULL);
77 return *ptr_;
78 }
79 C* operator->() const {
80 assert(ptr_ != NULL);
81 return ptr_;
82 }
83 C* get() const { return ptr_; }
84
85 // Comparison operators.
86 // These return whether a scoped_ptr and a raw pointer refer to
87 // the same object, not just to two different but equal objects.
88 bool operator==(const C* p) const { return ptr_ == p; }
89 bool operator!=(const C* p) const { return ptr_ != p; }
90
91 // Swap two scoped pointers.
92 void swap(scoped_ptr& p2) {
93 C* tmp = ptr_;
94 ptr_ = p2.ptr_;
95 p2.ptr_ = tmp;
96 }
97
98 // Release a pointer.
99 // The return value is the current pointer held by this object.
100 // If this object holds a NULL pointer, the return value is NULL.
101 // After this operation, this object will hold a NULL pointer,
102 // and will not own the object any more.
103 C* release() {
104 C* retVal = ptr_;
105 ptr_ = NULL;
106 return retVal;
107 }
108
109 private:
110 C* ptr_;
111
112 // google3 friend class that can access copy ctor (although if it actually
113 // calls a copy ctor, there will be a problem) see below
114 friend scoped_ptr<C> make_scoped_ptr<C>(C *p);
115
116 // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't
117 // make sense, and if C2 == C, it still doesn't make sense because you should
118 // never have the same object owned by two different scoped_ptrs.
119 template <class C2> bool operator==(scoped_ptr<C2> const& p2) const;
120 template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const;
121
122 // Disallow evil constructors
123 scoped_ptr(const scoped_ptr&);
124 void operator=(const scoped_ptr&);
125};
126
127// Free functions
128template <class C>
129inline void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) {
130 p1.swap(p2);
131}
132
133template <class C>
134inline bool operator==(const C* p1, const scoped_ptr<C>& p2) {
135 return p1 == p2.get();
136}
137
138template <class C>
139inline bool operator==(const C* p1, const scoped_ptr<const C>& p2) {
140 return p1 == p2.get();
141}
142
143template <class C>
144inline bool operator!=(const C* p1, const scoped_ptr<C>& p2) {
145 return p1 != p2.get();
146}
147
148template <class C>
149inline bool operator!=(const C* p1, const scoped_ptr<const C>& p2) {
150 return p1 != p2.get();
151}
152
153template <class C>
154scoped_ptr<C> make_scoped_ptr(C *p) {
155 // This does nothing but to return a scoped_ptr of the type that the passed
156 // pointer is of. (This eliminates the need to specify the name of T when
157 // making a scoped_ptr that is used anonymously/temporarily.) From an
158 // access control point of view, we construct an unnamed scoped_ptr here
159 // which we return and thus copy-construct. Hence, we need to have access
160 // to scoped_ptr::scoped_ptr(scoped_ptr const &). However, it is guaranteed
161 // that we never actually call the copy constructor, which is a good thing
162 // as we would call the temporary's object destructor (and thus delete p)
163 // if we actually did copy some object, here.
164 return scoped_ptr<C>(p);
165}
166
167// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
168// with new [] and the destructor deletes objects with delete [].
169//
170// As with scoped_ptr<C>, a scoped_array<C> either points to an object
171// or is NULL. A scoped_array<C> owns the object that it points to.
172// scoped_array<T> is thread-compatible, and once you index into it,
173// the returned objects have only the threadsafety guarantees of T.
174//
175// Size: sizeof(scoped_array<C>) == sizeof(C*)
176template <class C>
177class scoped_array {
178 public:
179
180 // The element type
181 typedef C element_type;
182
183 // Constructor. Defaults to intializing with NULL.
184 // There is no way to create an uninitialized scoped_array.
185 // The input parameter must be allocated with new [].
186 explicit scoped_array(C* p = NULL) : array_(p) { }
187
188 // Destructor. If there is a C object, delete it.
189 // We don't need to test ptr_ == NULL because C++ does that for us.
190 ~scoped_array() {
191 enum { type_must_be_complete = sizeof(C) };
192 delete[] array_;
193 }
194
195 // Reset. Deletes the current owned object, if any.
196 // Then takes ownership of a new object, if given.
197 // this->reset(this->get()) works.
198 void reset(C* p = NULL) {
199 if (p != array_) {
200 enum { type_must_be_complete = sizeof(C) };
201 delete[] array_;
202 array_ = p;
203 }
204 }
205
206 // Get one element of the current object.
207 // Will assert() if there is no current object, or index i is negative.
208 C& operator[](std::ptrdiff_t i) const {
209 assert(i >= 0);
210 assert(array_ != NULL);
211 return array_[i];
212 }
213
214 // Get a pointer to the zeroth element of the current object.
215 // If there is no current object, return NULL.
216 C* get() const {
217 return array_;
218 }
219
220 // Comparison operators.
221 // These return whether a scoped_array and a raw pointer refer to
222 // the same array, not just to two different but equal arrays.
223 bool operator==(const C* p) const { return array_ == p; }
224 bool operator!=(const C* p) const { return array_ != p; }
225
226 // Swap two scoped arrays.
227 void swap(scoped_array& p2) {
228 C* tmp = array_;
229 array_ = p2.array_;
230 p2.array_ = tmp;
231 }
232
233 // Release an array.
234 // The return value is the current pointer held by this object.
235 // If this object holds a NULL pointer, the return value is NULL.
236 // After this operation, this object will hold a NULL pointer,
237 // and will not own the object any more.
238 C* release() {
239 C* retVal = array_;
240 array_ = NULL;
241 return retVal;
242 }
243
244 private:
245 C* array_;
246
247 // Forbid comparison of different scoped_array types.
248 template <class C2> bool operator==(scoped_array<C2> const& p2) const;
249 template <class C2> bool operator!=(scoped_array<C2> const& p2) const;
250
251 // Disallow evil constructors
252 scoped_array(const scoped_array&);
253 void operator=(const scoped_array&);
254};
255
256// Free functions
257template <class C>
258inline void swap(scoped_array<C>& p1, scoped_array<C>& p2) {
259 p1.swap(p2);
260}
261
262template <class C>
263inline bool operator==(const C* p1, const scoped_array<C>& p2) {
264 return p1 == p2.get();
265}
266
267template <class C>
268inline bool operator==(const C* p1, const scoped_array<const C>& p2) {
269 return p1 == p2.get();
270}
271
272template <class C>
273inline bool operator!=(const C* p1, const scoped_array<C>& p2) {
274 return p1 != p2.get();
275}
276
277template <class C>
278inline bool operator!=(const C* p1, const scoped_array<const C>& p2) {
279 return p1 != p2.get();
280}
281
282// This class wraps the c library function free() in a class that can be
283// passed as a template argument to scoped_ptr_malloc below.
284class ScopedPtrMallocFree {
285 public:
286 inline void operator()(void* x) const {
287 free(x);
288 }
289};
290
291// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
292// second template argument, the functor used to free the object.
293
294template<class C, class FreeProc = ScopedPtrMallocFree>
295class scoped_ptr_malloc {
296 public:
297
298 // The element type
299 typedef C element_type;
300
301 // Construction with no arguments sets ptr_ to NULL.
302 // There is no way to create an uninitialized scoped_ptr.
303 // The input parameter must be allocated with an allocator that matches the
304 // Free functor. For the default Free functor, this is malloc, calloc, or
305 // realloc.
306 explicit scoped_ptr_malloc(): ptr_(NULL) { }
307
308 // Construct with a C*, and provides an error with a D*.
309 template<class must_be_C>
310 explicit scoped_ptr_malloc(must_be_C* p): ptr_(p) { }
311
312 // Construct with a void*, such as you get from malloc.
313 explicit scoped_ptr_malloc(void *p): ptr_(static_cast<C*>(p)) { }
314
315 // Destructor. If there is a C object, call the Free functor.
316 ~scoped_ptr_malloc() {
317 free_(ptr_);
318 }
319
320 // Reset. Calls the Free functor on the current owned object, if any.
321 // Then takes ownership of a new object, if given.
322 // this->reset(this->get()) works.
323 void reset(C* p = NULL) {
324 if (ptr_ != p) {
325 free_(ptr_);
326 ptr_ = p;
327 }
328 }
329
330 // Reallocates the existing pointer, and returns 'true' if
331 // the reallcation is succesfull. If the reallocation failed, then
332 // the pointer remains in its previous state.
333 //
334 // Note: this calls realloc() directly, even if an alternate 'free'
335 // functor is provided in the template instantiation.
336 bool try_realloc(size_t new_size) {
337 C* new_ptr = static_cast<C*>(realloc(ptr_, new_size));
338 if (new_ptr == NULL) {
339 return false;
340 }
341 ptr_ = new_ptr;
342 return true;
343 }
344
345 // Get the current object.
346 // operator* and operator-> will cause an assert() failure if there is
347 // no current object.
348 C& operator*() const {
349 assert(ptr_ != NULL);
350 return *ptr_;
351 }
352
353 C* operator->() const {
354 assert(ptr_ != NULL);
355 return ptr_;
356 }
357
358 C* get() const {
359 return ptr_;
360 }
361
362 // Comparison operators.
363 // These return whether a scoped_ptr_malloc and a plain pointer refer
364 // to the same object, not just to two different but equal objects.
365 // For compatibility with the boost-derived implementation, these
366 // take non-const arguments.
367 bool operator==(C* p) const {
368 return ptr_ == p;
369 }
370
371 bool operator!=(C* p) const {
372 return ptr_ != p;
373 }
374
375 // Swap two scoped pointers.
376 void swap(scoped_ptr_malloc & b) {
377 C* tmp = b.ptr_;
378 b.ptr_ = ptr_;
379 ptr_ = tmp;
380 }
381
382 // Release a pointer.
383 // The return value is the current pointer held by this object.
384 // If this object holds a NULL pointer, the return value is NULL.
385 // After this operation, this object will hold a NULL pointer,
386 // and will not own the object any more.
387 C* release() {
388 C* tmp = ptr_;
389 ptr_ = NULL;
390 return tmp;
391 }
392
393 private:
394 C* ptr_;
395
396 // no reason to use these: each scoped_ptr_malloc should have its own object
397 template <class C2, class GP>
398 bool operator==(scoped_ptr_malloc<C2, GP> const& p) const;
399 template <class C2, class GP>
400 bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const;
401
402 static FreeProc const free_;
403
404 // Disallow evil constructors
405 scoped_ptr_malloc(const scoped_ptr_malloc&);
406 void operator=(const scoped_ptr_malloc&);
407};
408
409template<class C, class FP>
410FP const scoped_ptr_malloc<C, FP>::free_ = FP();
411
412template<class C, class FP> inline
413void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) {
414 a.swap(b);
415}
416
417template<class C, class FP> inline
418bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) {
419 return p == b.get();
420}
421
422template<class C, class FP> inline
423bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) {
424 return p != b.get();
425}
426
427#endif // BASE_SCOPED_PTR_H__
428