LTP GCOV extension - code coverage report
Current view: directory - usr/include/xapian - base.h
Test: lcov.info
Date: 2008-08-14 Instrumented lines: 11
Code covered: 45.5 % Executed lines: 5

       1                 : /* base.h: Reference-counted pointers
       2                 :  *
       3                 :  * Copyright 1999,2000,2001 BrightStation PLC
       4                 :  * Copyright 2002 Ananova Ltd
       5                 :  * Copyright 2002,2003,2004,2007 Olly Betts
       6                 :  *
       7                 :  * This program is free software; you can redistribute it and/or
       8                 :  * modify it under the terms of the GNU General Public License as
       9                 :  * published by the Free Software Foundation; either version 2 of the
      10                 :  * License, or (at your option) any later version.
      11                 :  *
      12                 :  * This program is distributed in the hope that it will be useful,
      13                 :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15                 :  * GNU General Public License for more details.
      16                 :  *
      17                 :  * You should have received a copy of the GNU General Public License
      18                 :  * along with this program; if not, write to the Free Software
      19                 :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
      20                 :  * USA
      21                 :  */
      22                 : 
      23                 : #ifndef XAPIAN_INCLUDED_BASE_H
      24                 : #define XAPIAN_INCLUDED_BASE_H
      25                 : 
      26                 : #include <xapian/deprecated.h>
      27                 : 
      28                 : namespace Xapian {
      29                 : namespace Internal {
      30                 : 
      31                 : /** @internal Reference counted internal classes should inherit from RefCntBase.
      32                 :  *
      33                 :  * This gives the object a reference count used by RefCntPtr.
      34                 :  */
      35                 : class RefCntBase {
      36                 :     /* Note: We never delete a pointer to a subclass of RefCntBase using
      37                 :      * a RefCntBase *, so we don't need a virtual destructor here.
      38                 :      */
      39                 :     protected:
      40                 :         /** The copy constructor.
      41                 :          *
      42                 :          *  This is protected since it'll only be used by derived classes,
      43                 :          *  which should only rarely need copying (this is, after all, a
      44                 :          *  refcount implementation).  Sometimes it's needed, though,
      45                 :          *  since we need to zero ref_count in the copy.
      46                 :          */
      47                 :         RefCntBase(const RefCntBase &) : ref_count(0) { }
      48                 : 
      49                 :     public:
      50                 :         /// The constructor, which initialises the ref_count to 0.
      51                 :         RefCntBase() : ref_count(0) { }
      52                 : 
      53                 :         typedef unsigned int ref_count_t;
      54                 : 
      55                 :         /** The actual reference count.  It's mutable so we can have reference
      56                 :          *  counting work with const pointers.
      57                 :          */
      58                 :         mutable ref_count_t ref_count;
      59                 : };
      60                 : 
      61                 : /** @internal A reference-counted pointer.  Can be used with any
      62                 :  *  class derived from RefCntBase, as long as it is allocated
      63                 :  *  on the heap by new (not new[]!).
      64                 :  */
      65                 : template <class T>
      66                 : class RefCntPtr {
      67                 :     private:
      68                 :         T *dest;
      69                 : 
      70                 :     public:
      71                 :         T *operator->() const;
      72                 :         T &operator*() const;
      73                 :         T *get() const;
      74                 :         /** Make a RefCntPtr for an object which may already
      75                 :          *  have reference counted pointers.
      76                 :          *
      77                 :          *  You usually pass in a newly created object, or an object may pass
      78                 :          *  in "this" to get a RefCntPtr to itself to pass to other classes.
      79                 :          *  (e.g. a database might pass a newly created postlist a reference
      80                 :          *  counted pointer to itself.)
      81                 :          */
      82                 :         RefCntPtr(T *dest_);
      83                 :         RefCntPtr();
      84                 :         RefCntPtr(const RefCntPtr &other);
      85                 :         void operator=(const RefCntPtr &other);
      86                 :         void operator=(T *dest_);
      87                 :         ~RefCntPtr();
      88                 : 
      89                 :         template <class U>
      90                 :         RefCntPtr(const RefCntPtr<U> &other);
      91                 : };
      92                 : 
      93                 : template <class T>
      94              19 : inline RefCntPtr<T>::RefCntPtr(T *dest_) : dest(dest_)
      95                 : {
      96              19 :     if (dest) ++dest->ref_count;
      97              19 : }
      98                 : 
      99                 : template <class T>
     100                 : inline RefCntPtr<T>::RefCntPtr() : dest(0)
     101                 : {
     102                 : }
     103                 : 
     104                 : template <class T>
     105                 : inline RefCntPtr<T>::RefCntPtr(const RefCntPtr &other) : dest(other.dest)
     106                 : {
     107                 :     if (dest) ++dest->ref_count;
     108                 : }
     109                 : 
     110                 : template <class T>
     111                 : inline void RefCntPtr<T>::operator=(const RefCntPtr &other) {
     112                 :     operator=(other.dest);
     113                 : }
     114                 : 
     115                 : template <class T>
     116                 : inline void RefCntPtr<T>::operator=(T *dest_) {
     117                 :     // check if we're assigning a pointer to itself
     118                 :     if (dest == dest_) return;
     119                 : 
     120                 :     // copy the new dest in before we delete the old to avoid a small
     121                 :     // window in which dest points to a deleted object
     122                 :     // FIXME: if pointer assignment isn't atomic, we ought to use locking...
     123                 :     T *old_dest = dest;
     124                 :     dest = dest_;
     125                 :     if (dest) ++dest->ref_count;
     126                 :     if (old_dest && --old_dest->ref_count == 0) delete old_dest;
     127                 : }
     128                 : 
     129                 : template <class T>
     130               0 : inline RefCntPtr<T>::~RefCntPtr()
     131                 : {
     132               0 :     if (dest && --dest->ref_count == 0) {
     133                 :         // zero before we delete to avoid a small window in which dest points
     134                 :         // to a deleted object
     135                 :         // FIXME: if pointer assignment isn't atomic, we ought to use locking...
     136               0 :         T * condemned = dest;
     137               0 :         dest = 0;
     138               0 :         delete condemned;
     139                 :     }
     140               0 : }
     141                 : 
     142                 : template <class T>
     143                 : template <class U>
     144                 : inline
     145                 : RefCntPtr<T>::RefCntPtr(const RefCntPtr<U> &other)
     146                 :         : dest(other.get())
     147                 : {
     148                 :     if (dest) ++dest->ref_count;
     149                 : }
     150                 : 
     151                 : template <class T>
     152                 : inline T *RefCntPtr<T>::operator->() const
     153                 : {
     154                 :     return dest;
     155                 : }
     156                 : 
     157                 : template <class T>
     158                 : inline T &RefCntPtr<T>::operator*() const
     159                 : {
     160                 :     return *dest;
     161                 : }
     162                 : 
     163                 : template <class T>
     164              30 : inline T *RefCntPtr<T>::get() const
     165                 : {
     166              30 :     return dest;
     167                 : }
     168                 : 
     169                 : }
     170                 : }
     171                 : 
     172                 : #endif /* XAPIAN_INCLUDED_BASE_H */

Generated by: LTP GCOV extension version 1.6