LCOV - code coverage report
Current view: directory - src/include - nacl_scoped_ptr.h (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 23 23 100.0 %
Date: 2014-06-18 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                 :   // 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_

Generated by: LCOV version 1.7