LCOV - code coverage report
Current view: directory - src/trusted/nacl_base - nacl_refcount.h (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 16 12 75.0 %
Date: 2012-02-16 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2011 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : #ifndef NATIVE_CLIENT_SRC_TRUSTED_NACL_BASE_NACL_REFCOUNT_H_
       8                 : #define NATIVE_CLIENT_SRC_TRUSTED_NACL_BASE_NACL_REFCOUNT_H_
       9                 : 
      10                 : #include "native_client/src/include/nacl_base.h"
      11                 : #include "native_client/src/include/portability.h"
      12                 : 
      13                 : #include "native_client/src/shared/platform/nacl_sync.h"
      14                 : 
      15                 : #ifdef __cplusplus
      16                 : # include "native_client/src/include/nacl_scoped_ptr.h"
      17                 : # define NACL_IS_REFCOUNT_SUBCLASS  ; typedef char is_refcount_subclass
      18                 : #else
      19                 : # define NACL_IS_REFCOUNT_SUBCLASS
      20                 : #endif
      21                 : 
      22                 : EXTERN_C_BEGIN
      23                 : 
      24                 : /*
      25                 :  * Yields an lvalue of the vtable pointer, when given a subclass of
      26                 :  * NaClRefCount and a pointer to an instance -- with the convention
      27                 :  * that the vtable pointer is at the first word.
      28                 :  *
      29                 :  * Since we have the naming convention that struct Type contains an
      30                 :  * element of type struct TypeVtbl *, we make it so that less typing
      31                 :  * is required for the use of the macro and automatically constructing
      32                 :  * the vtable type name from the subclass name.
      33                 :  */
      34                 : #define NACL_VTBL(type, ptr) \
      35                 :   (*(struct type ## Vtbl const **) (void *) ptr)
      36                 : 
      37                 : struct NaClRefCountVtbl;
      38                 : 
      39                 : struct NaClRefCount {
      40                 :   struct NaClRefCountVtbl const *vtbl NACL_IS_REFCOUNT_SUBCLASS;
      41                 :   /* private */
      42                 :   struct NaClMutex              mu;
      43                 :   size_t                        ref_count;
      44                 : };
      45                 : 
      46                 : struct NaClRefCountVtbl {
      47                 :   void (*Dtor)(struct NaClRefCount  *vself);
      48                 : };
      49                 : 
      50                 : /*
      51                 :  * Placement new style ctor; creates w/ ref_count of 1.
      52                 :  *
      53                 :  * The subclasses' ctor must call this base class ctor during their
      54                 :  * contruction.
      55                 :  */
      56                 : int NaClRefCountCtor(struct NaClRefCount *nrcp) NACL_WUR;
      57                 : 
      58                 : struct NaClRefCount *NaClRefCountRef(struct NaClRefCount *nrcp);
      59                 : 
      60                 : /* when ref_count reaches zero, will call dtor and free */
      61                 : void NaClRefCountUnref(struct NaClRefCount *nrcp);
      62                 : 
      63                 : /*
      64                 :  * NaClRefCountSafeUnref is just like NaCRefCountUnref, except that
      65                 :  * nrcp may be NULL (in which case this is a noop).
      66                 :  *
      67                 :  * Used in failure cleanup of initialization code, esp in Ctors that
      68                 :  * can fail.
      69                 :  */
      70                 : void NaClRefCountSafeUnref(struct NaClRefCount *nrcp);
      71                 : 
      72                 : extern struct NaClRefCountVtbl const kNaClRefCountVtbl;
      73                 : 
      74                 : EXTERN_C_END
      75                 : 
      76                 : #ifdef __cplusplus
      77                 : 
      78                 : namespace nacl {
      79                 : 
      80                 : // syntactic glucose to handle transferring responsibility to release
      81                 : // uninitialized memory from a scoped_ptr_malloc to a scoped pointer
      82                 : // that handles dereferencing a refcounted object.
      83                 : 
      84                 : class NaClScopedRefCountNaClDescDtor {
      85                 :  public:
      86               0 :   inline void operator()(NaClRefCount* x) const {
      87               0 :     NaClRefCountUnref(x);
      88               0 :   }
      89                 : };
      90                 : 
      91                 : // RC must be a NaClRefCount subclass.  unfortunately we can only
      92                 : // enforce this by checking that the RC struct contains a common
      93                 : // attribute -- the NACL_IS_REFCOUNT_SUBCLASS macro must be included
      94                 : // for every subclass that wants to use this template
      95                 : template <typename RC, typename DtorProc = NaClScopedRefCountNaClDescDtor>
      96                 : class scoped_ptr_nacl_refcount {
      97                 :  public:
      98                 :   // standard ctor
      99               5 :   scoped_ptr_nacl_refcount(nacl::scoped_ptr_malloc<RC>* p, int ctor_fn_result)
     100               5 :       : ptr_(NULL) {
     101                 :     enum { must_be_subclass = sizeof(typename RC::is_refcount_subclass) };
     102                 : 
     103               5 :     if (ctor_fn_result) {
     104                 :       // we are now responsible for calling the unref, which, if the
     105                 :       // refcount drops to zero, will handle the free.
     106               5 :       ptr_ = p->release();
     107                 :     }
     108                 :   }
     109                 : 
     110                 :   // copy ctor
     111                 :   scoped_ptr_nacl_refcount(scoped_ptr_nacl_refcount const& other) {
     112                 :     ptr_ = NaClRefCountRef(other.ptr_);
     113                 :   }
     114                 : 
     115                 :   // assign
     116                 :   scoped_ptr_nacl_refcount& operator=(scoped_ptr_nacl_refcount const& other) {
     117                 :     if (this != &other) {  // exclude self-assignment, which should be no-op
     118                 :       if (NULL != ptr_) {
     119                 :         deref_(reinterpret_cast<NaClRefCount*>(ptr_));
     120                 :       }
     121                 :       ptr_ = NaClRefCountRef(other.ptr_);
     122                 :     }
     123                 :     return *this;
     124                 :   }
     125                 : 
     126               5 :   ~scoped_ptr_nacl_refcount() {
     127               5 :     if (NULL != ptr_) {
     128               0 :       deref_(reinterpret_cast<NaClRefCount*>(ptr_));
     129                 :     }
     130                 :   }
     131                 : 
     132               5 :   bool constructed() { return NULL != ptr_; }
     133                 : 
     134                 :   void reset(nacl::scoped_ptr_malloc<RC>* p = NULL, int ctor_fn_result = 0) {
     135                 :     if (NULL != ptr_) {
     136                 :       deref_(reinterpret_cast<NaClRefCount*>(ptr_));
     137                 :       ptr_ = NULL;
     138                 :     }
     139                 :     if (0 != ctor_fn_result) {
     140                 :       ptr_ = p->release();
     141                 :     }
     142                 :   }
     143                 : 
     144                 :   // Accessors
     145                 :   RC& operator*() const {
     146                 :     return *ptr_;
     147                 :   }
     148                 : 
     149                 :   RC* operator->() const {
     150                 :     return ptr_;
     151                 :   }
     152                 : 
     153                 :   RC* get() const { return ptr_; }
     154                 : 
     155                 :   /*
     156                 :    * ptr eq, so same pointer, and not equality testing on contents.
     157                 :    */
     158                 :   bool operator==(nacl::scoped_ptr_malloc<RC> const& p) const {
     159                 :     return ptr_ == p.get();
     160                 :   }
     161                 :   bool operator==(RC const* p) const { return ptr_ == p; }
     162                 : 
     163                 :   bool operator!=(nacl::scoped_ptr_malloc<RC> const& p) const {
     164                 :     return ptr_ != p.get();
     165                 :   }
     166                 :   bool operator!=(RC const* p) const { return ptr_ != p; }
     167                 : 
     168                 :   void swap(scoped_ptr_nacl_refcount& p2) {
     169                 :     RC* tmp = ptr_;
     170                 :     ptr_ = p2.ptr_;
     171                 :     p2.ptr_ = tmp;
     172                 :   }
     173                 : 
     174               5 :   RC* release() {
     175               5 :     RC* tmp = ptr_;
     176               5 :     ptr_ = NULL;
     177               5 :     return tmp;
     178                 :   }
     179                 : 
     180                 :  private:
     181                 :   RC* ptr_;
     182                 : 
     183                 :   static DtorProc const deref_;
     184                 : };
     185                 : 
     186                 : template<typename RC, typename DP>
     187              12 : DP const scoped_ptr_nacl_refcount<RC, DP>::deref_ = DP();
     188                 : 
     189                 : template<typename RC, typename DP>
     190                 : void swap(scoped_ptr_nacl_refcount<RC, DP>& a,
     191                 :           scoped_ptr_nacl_refcount<RC, DP>& b) {
     192                 :   a.swap(b);
     193                 : }
     194                 : 
     195                 : template<typename RC, typename DP> inline
     196                 : bool operator==(nacl::scoped_ptr_malloc<RC> const& a,
     197                 :                 scoped_ptr_nacl_refcount<RC, DP> const& b) {
     198                 :   return a.get() == b.get();
     199                 : }
     200                 : 
     201                 : template<class RC, typename DP> inline
     202                 : bool operator==(RC const* a,
     203                 :                 scoped_ptr_nacl_refcount<RC, DP> const& b) {
     204                 :   return a == b.get();
     205                 : }
     206                 : 
     207                 : template<typename RC, typename DP> inline
     208                 : bool operator!=(nacl::scoped_ptr_malloc<RC> const& a,
     209                 :                 scoped_ptr_nacl_refcount<RC, DP> const& b) {
     210                 :   return a.get() != b.get();
     211                 : }
     212                 : 
     213                 : template<typename RC, typename DP> inline
     214                 : bool operator!=(RC const* a,
     215                 :                 scoped_ptr_nacl_refcount<RC, DP> const& b) {
     216                 :   return a != b.get();
     217                 : }
     218                 : 
     219                 : }  // namespace
     220                 : 
     221                 : #endif
     222                 : 
     223                 : #endif

Generated by: LCOV version 1.7