SptrRefCount.hxx
上传用户:sy_wanhua
上传日期:2013-07-25
资源大小:3048k
文件大小:12k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. #ifndef SPTR_REFCOUNT_HXX_
  2. #define SPTR_REFCOUNT_HXX_
  3. /* ====================================================================
  4.  * The Vovida Software License, Version 1.0 
  5.  * 
  6.  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
  7.  * 
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in
  17.  *    the documentation and/or other materials provided with the
  18.  *    distribution.
  19.  * 
  20.  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
  21.  *    and "Vovida Open Communication Application Library (VOCAL)" must
  22.  *    not be used to endorse or promote products derived from this
  23.  *    software without prior written permission. For written
  24.  *    permission, please contact vocal@vovida.org.
  25.  *
  26.  * 4. Products derived from this software may not be called "VOCAL", nor
  27.  *    may "VOCAL" appear in their name, without prior written
  28.  *    permission of Vovida Networks, Inc.
  29.  * 
  30.  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
  31.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  32.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
  33.  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
  34.  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
  35.  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
  36.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  37.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  38.  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  39.  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  40.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  41.  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  42.  * DAMAGE.
  43.  * 
  44.  * ====================================================================
  45.  * 
  46.  * This software consists of voluntary contributions made by Vovida
  47.  * Networks, Inc. and many individuals on behalf of Vovida Networks,
  48.  * Inc.  For more information on Vovida Networks, Inc., please see
  49.  * <http://www.vovida.org/>.
  50.  *
  51.  */
  52. static const char* const Sptr_RefCount_hxx_Version =
  53.     "$Id: SptrRefCount.hxx,v 1.5 2001/05/23 01:51:47 bko Exp $";
  54. #include <assert.h>
  55. #include "VMutex.h"
  56. #include "debug.h"
  57. #include "CountSemaphore.hxx"
  58. #define SPTR_DEBUG 1
  59. #define SPTR_TRACEBACK 1
  60. #ifdef CODE_OPTIMIZE
  61. // turn off debugging and tracebacks in optimized code
  62. #undef SPTR_DEBUG
  63. #undef SPTR_TRACEBACK
  64. #define SPTR_DEBUG 0
  65. #define SPTR_TRACEBACK 0
  66. #endif
  67. #if SPTR_DEBUG
  68. #include <map>
  69. /** assists in debugging Sptrs (both use and implementation), by
  70.  * constructing a map of currently active Sptrs.  A singleton. */
  71. class SptrDebugger
  72. {
  73.     private:
  74. /// default constructor
  75.         SptrDebugger();
  76. /// used to get an instance.  If no instance exists, create one
  77.         static SptrDebugger* getInstance();
  78.         typedef map < void*, bool > PtrMap;
  79.         static SptrDebugger* impl_;
  80.         PtrMap ptrsInUse;
  81.         VMutex mutex;
  82.     public:
  83. /// add a new pointer when it is new.
  84.         static void newPtr(void* ptr);
  85. /// remove an pointer after it has been deleted.
  86.         static void deletePtr(void* ptr);
  87. };
  88. // these functions are used as debug breakpoints if SPTR_TRACEBACK
  89. // is set to 1
  90. void sptrDebugMarkTraceback(void* sptr, void* ptr);
  91. void sptrDebugClearTraceback(void* sptr, void* ptr);
  92. void sptrDebugDumpTraceback(char* filename);
  93. #endif
  94. /* TODO: this should be implemented via the CountSemaphore abstraction
  95.    (which should be renamed ) */
  96. /** Template simulates a "smart" pointer which deletes the item it is
  97.     pointing to when no more references to the item exist.  Warning:
  98.     circular references will produce memory leaks. 
  99.     
  100.     <P>Note that only one Sptr should be constructed from the original
  101.     ptr -- Sptr will free twice (and cause havoc) if it is misused like so:
  102.     <P>
  103.     <B> WRONG: </B>
  104.     <PRE>
  105.         T* obj = new T();
  106.         Sptr<T> p;
  107.         Sptr<T> q;
  108.         p = obj;
  109.         q = obj;  
  110.            <I>now both p and q think they are the only ones who will free the 
  111.               memory, so you will get an error.</i>
  112.     </PRE>
  113. */
  114. template < class T >
  115. class Sptr
  116. {
  117. private:
  118. mutable  T* ptr;
  119. mutable CountSemaphore* count;
  120. /// increment the reference count.
  121.         void increment()
  122.         {
  123.             if (ptr)
  124.             {
  125.                 if (!count)
  126.                 {
  127.                     count = new CountSemaphore();
  128.                 }
  129. count->increment();
  130.             }
  131. #if SPTR_TRACEBACK
  132.             sptrDebugMarkTraceback((void*) this, (void*) ptr);
  133. #endif
  134.         }
  135. /// decrement the reference count
  136.         void decrement()
  137.         {
  138.             if (ptr && count)
  139.             {
  140. #if SPTR_TRACEBACK
  141.                 sptrDebugClearTraceback((void*) this, (void*) ptr);
  142. #endif
  143. count->decrement();
  144.                 if (count->compare(0))
  145.                 {
  146. #if SPTR_DEBUG
  147. #if 0
  148.                     cerr << "deleting " << ptr << endl;
  149.                     breakpoint();
  150. #endif
  151.                     SptrDebugger::deletePtr((void*) ptr);
  152. #endif
  153.                     delete ptr;
  154.                     delete count;
  155.                 }
  156.             }
  157.             ptr = 0;
  158.             count = 0;
  159.         }
  160.     public:
  161. #if defined (__SUNPRO_CC)
  162. /** conversion operator converts pointers of this class to
  163.  * class Sptr< T2 >., where T2 is a different base class.  This
  164.  * is most often used when attempting to call a method of the
  165.  * base class through a derived class pointer.
  166.  */
  167.         template < class T2 >
  168.         operator Sptr<T2 > () 
  169.         {
  170.             return Sptr < T2 > (ptr, count);
  171.         }
  172. #endif
  173. /** conversion operator converts pointers of this const class
  174.  * to class const Sptr< T2 >., where T2 is a different base
  175.  * class.  This is most often used when attempting to call a
  176.  * const method of the base class through a derived class
  177.  * pointer.  This is a workaround for SUNPRO .
  178.  */
  179. template < class T2 >
  180.         operator const Sptr<T2 > () const
  181.         {
  182.             return Sptr < T2 > (ptr, count);
  183.         }
  184. /// default constructor.  points to NULL.
  185.         Sptr() : ptr(0), count(0)
  186.         {}
  187.         ;
  188. /** constructor used most often as the constructor from a
  189.  * plain pointer.  Do not use this to convert a single pointer
  190.  * to a smart pointer multiple times -- this will result in an
  191.  * error (see class introduction for details).
  192.  */
  193.         Sptr(T* original, CountSemaphore* myCount = 0)
  194.         : ptr(original), count(myCount)
  195.         {
  196.             if (ptr)
  197.             {
  198. #if SPTR_DEBUG
  199.                 if (!myCount)
  200.                 {
  201.                     SptrDebugger::newPtr((void*) ptr);  // void* takes away warning
  202.                 }
  203. #endif
  204.                 increment();
  205.             }
  206.         };
  207. /** copy constructor
  208.  */
  209.         Sptr(const Sptr& x)
  210.         : ptr(x.ptr), count(x.count)
  211.         {
  212.             increment();
  213.         };
  214. /// destructor
  215.         ~Sptr()
  216.         {
  217.             {
  218.                 decrement();
  219.             }
  220.         }
  221. /// dereference operator
  222.         T& operator*() const
  223.         {
  224.             assert(ptr);
  225.             return *ptr;
  226.         }
  227. /// ! operator .  Returns true if ptr == 0, false otherwise.
  228.         int operator!() const
  229.         {
  230.             if (ptr)
  231.             {
  232.                 return (ptr == 0);
  233.             }
  234.             else
  235.                 return true;
  236.         }
  237. /// pointer operator.
  238.         T* operator->() const
  239.         {
  240.             return ptr;
  241.         }
  242. /** dynamicCast works similarly to the actual dynamic_cast()
  243.  * operator, like so:
  244.  
  245.  <PRE>
  246.      class A {
  247.        ...
  248.      };
  249.      class B : public A {
  250.        ...
  251.      };
  252.      class C {
  253.        ...
  254.      };
  255.      ...
  256.      int main()
  257.      {
  258.  Sptr< A > a;
  259.  Sptr< B > b;
  260.  Sptr< C > c;
  261.  a = new B;
  262.  b.dynamicCast(a);
  263.  // now, b points to the same thing as a
  264.  c.dynamicCast(a);
  265.  // now, c is the NULL pointer.
  266.      }
  267.  </PRE>
  268.  */
  269.         template < class T2 > Sptr& dynamicCast(const Sptr < T2 > & x)
  270.         {
  271.             if (ptr == x.getPtr()) return *this;
  272.             decrement();
  273.             if(T* p = dynamic_cast < T* > (x.getPtr()))
  274.             {
  275.                 count = x.getCount();
  276.                 ptr = p;
  277.                 increment();
  278.             }
  279.             return *this;
  280.         }
  281. /** assignment operator -- this is most often used to assign
  282.  * from a smart pointer to a derived type to a smart pointer
  283.  * of the base type.
  284.  */
  285.         template < class T2 >
  286.         Sptr& operator=(const Sptr < T2 > & x)
  287.         {
  288.             if (ptr == x.getPtr()) return * this;
  289.             decrement();
  290.             ptr = x.getPtr();
  291.             count = x.getCount();
  292.             increment();
  293.             return *this;
  294.         }
  295. /** assignment operator from plain pointer.  Do not use this
  296.  * to convert a single pointer to a smart pointer multiple
  297.  * times -- this will result in an error (see class
  298.  * introduction for details).
  299.  */
  300.         Sptr& operator=(T* original)
  301.         {
  302.             if (ptr == original) return * this;
  303.             decrement();
  304. #if SPTR_DEBUG
  305.             SptrDebugger::newPtr((void*) original);
  306. #endif
  307.             ptr = original;
  308.             increment();
  309.             return *this;
  310.         };
  311. /// assignment operator
  312.         Sptr& operator=(const Sptr& x)
  313.         {
  314.             if (ptr == x.ptr) return * this;
  315.             decrement();
  316.             ptr = x.ptr;
  317.             count = x.count;
  318.             increment();
  319.             return *this;
  320.         }
  321. /// compare whether a pointer and a smart pointer point to different things
  322.         friend bool operator!=(const void* y, const Sptr& x)
  323. {
  324.             if (x.ptr != y)
  325.                 return true;
  326.             else
  327.                 return false;
  328. }
  329. /// compare whether a smart pointer and a pointer point to different things
  330.         friend bool operator!=(const Sptr& x, const void* y)
  331. {
  332.             if (x.ptr != y)
  333.                 return true;
  334.             else
  335.                 return false;
  336. }
  337. /// compare whether a pointer and a smart pointer point to the same thing
  338.         friend bool operator==(const void* y, const Sptr& x)
  339.         {
  340.             if (x.ptr == y)
  341.                 return true;
  342.             else
  343.                 return false;
  344.         }
  345. /// compare whether a smart pointer and a pointer point to the same thing
  346.         friend bool operator==(const Sptr& x, const void* y)
  347.         {
  348.             if (x.ptr == y)
  349.                 return true;
  350.             else
  351.                 return false;
  352.         }
  353. /// compare whether two smart pointers point to the same thing
  354.         bool operator==(const Sptr& x) const
  355.         {
  356.             if (x.ptr == ptr)
  357.                 return true;
  358.             else
  359.                 return false;
  360.         }
  361. /// compare whether two smart pointers point to the same thing
  362.         bool operator!=(const Sptr& x) const
  363.         {
  364.             if (x.ptr != ptr)
  365.                 return true;
  366.             else
  367.                 return false;
  368.         }
  369. /**
  370.    this interface is here because it may sometimes be
  371.    necessary.  DO NOT USE unless you must use it.
  372.    get the actual mutex of the smart pointer.
  373. */
  374.         VMutex* getMutex() const
  375.         {
  376.             return 0;
  377.         }
  378. /**
  379.    this interface is here because it may sometimes be
  380.    necessary.  DO NOT USE unless you must use it.
  381.    get the value of the reference count of the smart pointer.
  382. */
  383.         CountSemaphore* getCount() const
  384.         {
  385.             return count;
  386.         }
  387. /**
  388.    this interface is here because it may sometimes be
  389.    necessary.  DO NOT USE unless you must use it.
  390.    get the pointer to which the smart pointer points.
  391. */
  392.         T* getPtr() const
  393.         {
  394.             return ptr;
  395.         }
  396. };
  397. #endif