1 : // Copyright (c) 2011 The Native Client 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 : // Scopers help you manage ownership of a pointer, helping you easily manage the
6 : // a pointer within a scope, and automatically destroying the pointer at the
7 : // end of a scope. There are two main classes you will use, which coorespond
8 : // to the operators new/delete and new[]/delete[].
9 : //
10 : // Example usage (scoped_ptr):
11 : // {
12 : // scoped_ptr<Foo> foo(new Foo("wee"));
13 : // } // foo goes out of scope, releasing the pointer with it.
14 : //
15 : // {
16 : // scoped_ptr<Foo> foo; // No pointer managed.
17 : // foo.reset(new Foo("wee")); // Now a pointer is managed.
18 : // foo.reset(new Foo("wee2")); // Foo("wee") was destroyed.
19 : // foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed.
20 : // foo->Method(); // Foo::Method() called.
21 : // foo.get()->Method(); // Foo::Method() called.
22 : // SomeFunc(foo.release()); // SomeFunc takes owernship, foo no longer
23 : // // manages a pointer.
24 : // foo.reset(new Foo("wee4")); // foo manages a pointer again.
25 : // foo.reset(); // Foo("wee4") destroyed, foo no longer
26 : // // manages a pointer.
27 : // } // foo wasn't managing a pointer, so nothing was destroyed.
28 : //
29 : // Example usage (scoped_array):
30 : // {
31 : // scoped_array<Foo> foo(new Foo[100]);
32 : // foo.get()->Method(); // Foo::Method on the 0th element.
33 : // foo[10].Method(); // Foo::Method on the 10th element.
34 : // }
35 :
36 : #ifndef NATIVE_CLIENT_SRC_INCLUDE_NACL_SCOPED_PTR_H_
37 : #define NATIVE_CLIENT_SRC_INCLUDE_NACL_SCOPED_PTR_H_
38 :
39 : // This is an implementation designed to match the anticipated future TR2
40 : // implementation of the scoped_ptr class, and its closely-related brethren,
41 : // scoped_array, scoped_ptr_malloc.
42 :
43 : #include <assert.h>
44 : // TODO(sehr,noelallen): replace the C standard asserts with asserts that
45 : // use the same output as the logging interface when we have that.
46 : #include <stdlib.h>
47 : #include <cstddef>
48 :
49 : namespace nacl {
50 :
51 : // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
52 : // automatically deletes the pointer it holds (if any).
53 : // That is, scoped_ptr<T> owns the T object that it points to.
54 : // Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
55 : // Also like T*, scoped_ptr<T> is thread-compatible, and once you
56 : // dereference it, you get the threadsafety guarantees of T.
57 : //
58 : // The size of a scoped_ptr is small:
59 : // sizeof(scoped_ptr<C>) == sizeof(C*)
60 : template <class C>
61 : class scoped_ptr {
62 : public:
63 : // The element type
64 : typedef C element_type;
65 :
66 : // Constructor. Defaults to intializing with NULL.
67 : // There is no way to create an uninitialized scoped_ptr.
68 : // The input parameter must be allocated with new.
69 416 : explicit scoped_ptr(C* p = NULL) : ptr_(p) { }
70 :
71 : // Destructor. If there is a C object, delete it.
72 : // We don't need to test ptr_ == NULL because C++ does that for us.
73 159 : ~scoped_ptr() {
74 : enum { type_must_be_complete = sizeof(C) };
75 413 : delete ptr_;
76 318 : }
77 :
78 : // Reset. Deletes the current owned object, if any.
79 : // Then takes ownership of a new object, if given.
80 : // this->reset(this->get()) works.
81 108 : void reset(C* p = NULL) {
82 108 : if (p != ptr_) {
83 : enum { type_must_be_complete = sizeof(C) };
84 108 : delete ptr_;
85 108 : ptr_ = p;
86 108 : }
87 108 : }
88 :
89 : // Accessors to get the owned object.
90 : // operator* and operator-> will assert() if there is no current object.
91 : C& operator*() const {
92 : assert(ptr_ != NULL);
93 : return *ptr_;
94 : }
95 : C* operator->() const {
96 460 : assert(ptr_ != NULL);
97 230 : return ptr_;
98 : }
99 85 : C* get() const { return ptr_; }
100 :
101 : // Comparison operators.
102 : // These return whether two scoped_ptr refer to the same object, not just to
103 : // two different but equal objects.
104 88 : bool operator==(C* p) const { return ptr_ == p; }
105 5 : bool operator!=(C* p) const { return ptr_ != p; }
106 :
107 : // Swap two scoped pointers.
108 : void swap(scoped_ptr& p2) {
109 : C* tmp = ptr_;
110 : ptr_ = p2.ptr_;
111 : p2.ptr_ = tmp;
112 : }
113 :
114 : // Release a pointer.
115 : // The return value is the current pointer held by this object.
116 : // If this object holds a NULL pointer, the return value is NULL.
117 : // After this operation, this object will hold a NULL pointer,
118 : // and will not own the object any more.
119 : C* release() {
120 12 : C* retVal = ptr_;
121 12 : ptr_ = NULL;
122 12 : return retVal;
123 : }
124 :
125 : private:
126 : C* ptr_;
127 :
128 : // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't
129 : // make sense, and if C2 == C, it still doesn't make sense because you should
130 : // never have the same object owned by two different scoped_ptrs.
131 : template <class C2> bool operator==(scoped_ptr<C2> const& p2) const;
132 : template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const;
133 :
134 : // Disallow evil constructors
135 : scoped_ptr(const scoped_ptr&);
136 : void operator=(const scoped_ptr&);
137 : };
138 :
139 : // Free functions
140 : template <class C>
141 : void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) {
142 : p1.swap(p2);
143 : }
144 :
145 : template <class C>
146 : bool operator==(C* p1, const scoped_ptr<C>& p2) {
147 : return p1 == p2.get();
148 : }
149 :
150 : template <class C>
151 : bool operator!=(C* p1, const scoped_ptr<C>& p2) {
152 : return p1 != p2.get();
153 : }
154 :
155 : // scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
156 : // with new [] and the destructor deletes objects with delete [].
157 : //
158 : // As with scoped_ptr<C>, a scoped_array<C> either points to an object
159 : // or is NULL. A scoped_array<C> owns the object that it points to.
160 : // scoped_array<T> is thread-compatible, and once you index into it,
161 : // the returned objects have only the threadsafety guarantees of T.
162 : //
163 : // Size: sizeof(scoped_array<C>) == sizeof(C*)
164 : template <class C>
165 : class scoped_array {
166 : public:
167 : // The element type
168 : typedef C element_type;
169 :
170 : // Constructor. Defaults to intializing with NULL.
171 : // There is no way to create an uninitialized scoped_array.
172 : // The input parameter must be allocated with new [].
173 1234 : explicit scoped_array(C* p = NULL) : array_(p) { }
174 :
175 : // Destructor. If there is a C object, delete it.
176 : // We don't need to test array_ == NULL because C++ does that for us.
177 602 : ~scoped_array() {
178 : enum { type_must_be_complete = sizeof(C) };
179 1204 : delete[] array_;
180 1204 : }
181 :
182 : // Reset. Deletes the current owned object, if any.
183 : // Then takes ownership of a new object, if given.
184 : // this->reset(this->get()) works.
185 : void reset(C* p = NULL) {
186 : if (p != array_) {
187 : enum { type_must_be_complete = sizeof(C) };
188 : delete[] array_;
189 : array_ = p;
190 : }
191 : }
192 :
193 : // Get one element of the current object.
194 : // Will assert() if there is no current object, or index i is negative.
195 : C& operator[](std::ptrdiff_t i) const {
196 : assert(i >= 0);
197 : assert(array_ != NULL);
198 : return array_[i];
199 : }
200 :
201 : // Get a pointer to the zeroth element of the current object.
202 : // If there is no current object, return NULL.
203 : C* get() const {
204 27166 : return array_;
205 : }
206 :
207 : // Comparison operators.
208 : // These return whether two scoped_array refer to the same object, not just to
209 : // two different but equal objects.
210 : bool operator==(C* p) const { return array_ == p; }
211 : bool operator!=(C* p) const { return array_ != p; }
212 :
213 : // Swap two scoped arrays.
214 : void swap(scoped_array& p2) {
215 : C* tmp = array_;
216 : array_ = p2.array_;
217 : p2.array_ = tmp;
218 : }
219 :
220 : // Release an array.
221 : // The return value is the current pointer held by this object.
222 : // If this object holds a NULL pointer, the return value is NULL.
223 : // After this operation, this object will hold a NULL pointer,
224 : // and will not own the array any more.
225 : C* release() {
226 : C* retVal = array_;
227 : array_ = NULL;
228 : return retVal;
229 : }
230 :
231 : private:
232 : C* array_;
233 :
234 : // Forbid comparison of different scoped_array types.
235 : template <class C2> bool operator==(scoped_array<C2> const& p2) const;
236 : template <class C2> bool operator!=(scoped_array<C2> const& p2) const;
237 :
238 : // Disallow evil constructors
239 : scoped_array(const scoped_array&);
240 : void operator=(const scoped_array&);
241 : };
242 :
243 : // Free functions
244 : template <class C>
245 : void swap(scoped_array<C>& p1, scoped_array<C>& p2) {
246 : p1.swap(p2);
247 : }
248 :
249 : template <class C>
250 : bool operator==(C* p1, const scoped_array<C>& p2) {
251 : return p1 == p2.get();
252 : }
253 :
254 : template <class C>
255 : bool operator!=(C* p1, const scoped_array<C>& p2) {
256 : return p1 != p2.get();
257 : }
258 :
259 : // This class wraps the c library function free() in a class that can be
260 : // passed as a template argument to scoped_ptr_malloc below.
261 : class ScopedPtrMallocFree {
262 : public:
263 : inline void operator()(void* x) const {
264 : free(x);
265 : }
266 : };
267 :
268 : // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
269 : // second template argument, the functor used to free the object.
270 :
271 : template<class C, class FreeProc = ScopedPtrMallocFree>
272 : class scoped_ptr_malloc {
273 : public:
274 : // The element type
275 : typedef C element_type;
276 :
277 : // Constructor. Defaults to intializing with NULL.
278 : // There is no way to create an uninitialized scoped_ptr.
279 : // The input parameter must be allocated with an allocator that matches the
280 : // Free functor. For the default Free functor, this is malloc, calloc, or
281 : // realloc.
282 : explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {}
283 :
284 : // Destructor. If there is a C object, call the Free functor.
285 : ~scoped_ptr_malloc() {
286 : FreeProc free_proc;
287 : free_proc(ptr_);
288 : }
289 :
290 : // Reset. Calls the Free functor on the current owned object, if any.
291 : // Then takes ownership of a new object, if given.
292 : // this->reset(this->get()) works.
293 : void reset(C* p = NULL) {
294 : if (ptr_ != p) {
295 : FreeProc free_proc;
296 : free_proc(ptr_);
297 : ptr_ = p;
298 : }
299 : }
300 :
301 : // Get the current object.
302 : // operator* and operator-> will cause an assert() failure if there is
303 : // no current object.
304 : C& operator*() const {
305 : assert(ptr_ != NULL);
306 : return *ptr_;
307 : }
308 :
309 : C* operator->() const {
310 : assert(ptr_ != NULL);
311 : return ptr_;
312 : }
313 :
314 : C* get() const {
315 : return ptr_;
316 : }
317 :
318 : // Comparison operators.
319 : // These return whether a scoped_ptr_malloc and a plain pointer refer
320 : // to the same object, not just to two different but equal objects.
321 : // For compatibility wwith the boost-derived implementation, these
322 : // take non-const arguments.
323 : bool operator==(C* p) const {
324 : return ptr_ == p;
325 : }
326 :
327 : bool operator!=(C* p) const {
328 : return ptr_ != p;
329 : }
330 :
331 : // Swap two scoped pointers.
332 : void swap(scoped_ptr_malloc & b) {
333 : C* tmp = b.ptr_;
334 : b.ptr_ = ptr_;
335 : ptr_ = tmp;
336 : }
337 :
338 : // Release a pointer.
339 : // The return value is the current pointer held by this object.
340 : // If this object holds a NULL pointer, the return value is NULL.
341 : // After this operation, this object will hold a NULL pointer,
342 : // and will not own the object any more.
343 : C* release() {
344 : C* tmp = ptr_;
345 : ptr_ = NULL;
346 : return tmp;
347 : }
348 :
349 : private:
350 : C* ptr_;
351 :
352 : // no reason to use these: each scoped_ptr_malloc should have its own object
353 : template <class C2, class GP>
354 : bool operator==(scoped_ptr_malloc<C2, GP> const& p) const;
355 : template <class C2, class GP>
356 : bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const;
357 :
358 : // Disallow evil constructors
359 : scoped_ptr_malloc(const scoped_ptr_malloc&);
360 : void operator=(const scoped_ptr_malloc&);
361 : };
362 :
363 : template<class C, class FP> inline
364 : void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) {
365 : a.swap(b);
366 : }
367 :
368 : template<class C, class FP> inline
369 : bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) {
370 : return p == b.get();
371 : }
372 :
373 : template<class C, class FP> inline
374 : bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) {
375 : return p != b.get();
376 : }
377 :
378 : // See src/trusted/nacl_base/nacl_refcount.h for
379 : // scoped_ptr_nacl_refcount which is intended for use with
380 : // scoped_ptr_malloc and NaClRefCount objects.
381 :
382 : // See src/shared/platform/scoped_ptr_refcount.h for a refcount
383 : // pointer template class that is intended for general C++ objects,
384 : // but using the platform library's synchronization primitives.
385 :
386 : } // namespace
387 :
388 : #endif // NATIVE_CLIENT_SRC_INCLUDE_NACL_SCOPED_PTR_H_
|