LCOV - code coverage report
Current view: directory - src/include - nacl_scoped_ptr.h (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 51 39 76.5 %
Date: 2012-02-16 Functions: 0 0 -

       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_

Generated by: LCOV version 1.7