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