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

流媒体/Mpeg4/MP4

开发平台:

C/C++

  1. #ifndef SPTR_HXX_
  2. #define SPTR_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_hxx_Version =
  53.     "$Id: Sptr.hxx,v 1.37 2001/05/13 10:46:03 icahoon Exp $";
  54. #include "global.h"
  55. /// define this to use the refcount based version instead of the "normal" version
  56. #define USE_SPTR_REFCOUNT
  57. #if defined(USE_SPTR_REFCOUNT)
  58. #include "SptrRefCount.hxx"
  59. #else
  60. // do not use the SptrRefcount Implementation
  61. #define SPTR_DEBUG 1
  62. #define SPTR_TRACEBACK 1
  63. #include <assert.h>
  64. #include "VMutex.h"
  65. #include "debug.h"
  66. #if SPTR_DEBUG
  67. #include <map>
  68. /** assists in debugging Sptrs (both use and implementation), by
  69.  * constructing a map of currently active Sptrs.  A singleton. */
  70. class SptrDebugger
  71. {
  72.     private:
  73. /// default constructor
  74.         SptrDebugger();
  75. /// used to get an instance.  If no instance exists, create one
  76.         static SptrDebugger* getInstance();
  77.         typedef map < void*, bool > PtrMap;
  78.         static SptrDebugger* impl_;
  79.         PtrMap ptrsInUse;
  80.         VMutex mutex;
  81.     public:
  82. /// add a new pointer when it is new.
  83.         static void newPtr(void* ptr);
  84. /// remove an pointer after it has been deleted.
  85.         static void deletePtr(void* ptr);
  86. };
  87. // these functions are used as debug breakpoints if SPTR_TRACEBACK
  88. // is set to 1
  89. void sptrDebugMarkTraceback(void* sptr, void* ptr);
  90. void sptrDebugClearTraceback(void* sptr, void* ptr);
  91. void sptrDebugDumpTraceback(char* filename);
  92. #endif
  93. /* TODO: this should be implemented via the CountSemaphore abstraction
  94.    (which should be renamed ) */
  95. /** Template simulates a "smart" pointer which deletes the item it is
  96.     pointing to when no more references to the item exist.  Warning:
  97.     circular references will produce memory leaks. 
  98.     
  99.     <P>Note that only one Sptr should be constructed from the original
  100.     ptr -- Sptr will free twice (and cause havoc) if it is misused like so:
  101.     <P>
  102.     <B> WRONG: </B>
  103.     <PRE>
  104.         T* obj = new T();
  105.         Sptr<T> p;
  106.         Sptr<T> q;
  107.         p = obj;
  108.         q = obj;  
  109.            <I>now both p and q think they are the only ones who will free the 
  110.               memory, so you will get an error.</i>
  111.     </PRE>
  112. */
  113. template < class T >
  114. class Sptr
  115. {
  116. private:
  117. mutable  T* ptr;
  118.         mutable int* count;
  119.         mutable VMutex* mutex;
  120. /// increment the reference count.
  121.         void increment()
  122.         {
  123.             if (ptr)
  124.             {
  125.                 if (!count)
  126.                 {
  127.                     count = new int(0);
  128.                 }
  129.                 if (!mutex)
  130.                 {
  131.                     mutex = new VMutex;
  132.                 }
  133.                 mutex->lock();
  134.                 (*count)++;
  135.                 mutex->unlock();
  136.             }
  137. #if SPTR_TRACEBACK
  138.             sptrDebugMarkTraceback((void*) this, (void*) ptr);
  139. #endif
  140.         }
  141. /// decrement the reference count
  142.         void decrement()
  143.         {
  144.             if (ptr && count)
  145.             {
  146. #if SPTR_TRACEBACK
  147.                 sptrDebugClearTraceback((void*) this, (void*) ptr);
  148. #endif
  149.                 bool countIsZero;
  150.                 mutex->lock();
  151.                 (*count)--;
  152.                 countIsZero = (*count == 0);
  153.                 mutex->unlock();
  154.                 if (countIsZero)
  155.                 {
  156. #if SPTR_DEBUG
  157. #if 0
  158.                     cerr << "deleting " << ptr << endl;
  159.                     breakpoint();
  160. #endif
  161.                     SptrDebugger::deletePtr((void*) ptr);
  162. #endif
  163.                     delete ptr; ptr = 0;
  164.                     delete count; count = 0;
  165.                     delete mutex; mutex = 0;
  166.                 }
  167.             }
  168.             ptr = 0;
  169.             count = 0;
  170.             mutex = 0;
  171.         }
  172.     public:
  173. #if 1
  174. /** conversion operator converts pointers of this class to
  175.  * class Sptr< T2 >., where T2 is a different base class.  This
  176.  * is most often used when attempting to call a method of the
  177.  * base class through a derived class pointer.
  178.  */
  179.         template < class T2 >
  180.         operator Sptr<T2 > () 
  181.         {
  182.             return Sptr < T2 > (ptr, count, mutex);
  183.         }
  184. /** conversion operator converts pointers of this const class
  185.  * to class const Sptr< T2 >., where T2 is a different base
  186.  * class.  This is most often used when attempting to call a
  187.  * const method of the base class through a derived class
  188.  * pointer.
  189.  */
  190. template < class T2 >
  191.         operator const Sptr<T2 > () const
  192.         {
  193.             return Sptr < T2 > (ptr, count, mutex);
  194.         }
  195. #endif
  196. /// default constructor.  points to NULL.
  197.         Sptr() : ptr(0), count(0), mutex(0)
  198.         {}
  199.         ;
  200. /** constructor used most often as the constructor from a
  201.  * plain pointer.  Do not use this to convert a single pointer
  202.  * to a smart pointer multiple times -- this will result in an
  203.  * error (see class introduction for details).
  204.  */
  205.         Sptr(T* original, int* myCount = 0, VMutex* myMutex = 0)
  206.         : ptr(original), count(myCount), mutex(myMutex)
  207.         {
  208.             if (ptr)
  209.             {
  210. #if SPTR_DEBUG
  211.                 if (!myCount || !myMutex)
  212.                 {
  213.                     SptrDebugger::newPtr((void*) ptr);  // void* takes away warning
  214.                 }
  215. #endif
  216.                 increment();
  217.             }
  218.         };
  219. /** copy constructor
  220.  */
  221.         Sptr(const Sptr& x)
  222.         : ptr(x.ptr), count(x.count), mutex(x.mutex)
  223.         {
  224.             increment();
  225.         };
  226. /// destructor
  227.         ~Sptr()
  228.         {
  229.             {
  230.                 decrement();
  231.             }
  232.         }
  233. /// dereference operator
  234.         T& operator*() const
  235.         {
  236.             assert(ptr);
  237.             return *ptr;
  238.         }
  239. /// ! operator .  Returns true if ptr == 0, false otherwise.
  240.         int operator!() const
  241.         {
  242.             if (ptr)
  243.             {
  244.                 return (ptr == 0);
  245.             }
  246.             else
  247.                 return true;
  248.         }
  249. /// pointer operator.
  250.         T* operator->() const
  251.         {
  252.             return ptr;
  253.         }
  254. /** dynamicCast works similarly to the actual dynamic_cast()
  255.  * operator, like so:
  256.  
  257.  <PRE>
  258.      class A {
  259.        ...
  260.      };
  261.      class B : public A {
  262.        ...
  263.      };
  264.      class C {
  265.        ...
  266.      };
  267.      ...
  268.      int main()
  269.      {
  270.  Sptr< A > a;
  271.  Sptr< B > b;
  272.  Sptr< C > c;
  273.  a = new B;
  274.  b.dynamicCast(a);
  275.  // now, b points to the same thing as a
  276.  c.dynamicCast(a);
  277.  // now, c is the NULL pointer.
  278.      }
  279.  </PRE>
  280.  */
  281.         template < class T2 > Sptr& dynamicCast(const Sptr < T2 > & x)
  282.         {
  283.             if (ptr == x.getPtr()) return *this;
  284.             decrement();
  285.             if(T* p = dynamic_cast < T* > (x.getPtr()))
  286.             {
  287.                 count = x.getCount();
  288.                 mutex = x.getMutex();
  289.                 ptr = p;
  290.                 increment();
  291.             }
  292.             return *this;
  293.         }
  294. /** assignment operator -- this is most often used to assign
  295.  * from a smart pointer to a derived type to a smart pointer
  296.  * of the base type.
  297.  */
  298.         template < class T2 >
  299.         Sptr& operator=(const Sptr < T2 > & x)
  300.         {
  301.             if (ptr == x.getPtr()) return * this;
  302.             decrement();
  303.             ptr = x.getPtr();
  304.             count = x.getCount();
  305.             mutex = x.getMutex();
  306.             increment();
  307.             return *this;
  308.         }
  309. /** assignment operator from plain pointer.  Do not use this
  310.  * to convert a single pointer to a smart pointer multiple
  311.  * times -- this will result in an error (see class
  312.  * introduction for details).
  313.  */
  314.         Sptr& operator=(T* original)
  315.         {
  316.             if (ptr == original) return * this;
  317.             decrement();
  318. #if SPTR_DEBUG
  319.             SptrDebugger::newPtr((void*) original);
  320. #endif
  321.             ptr = original;
  322.             increment();
  323.             return *this;
  324.         };
  325. /// assignment operator
  326.         Sptr& operator=(const Sptr& x)
  327.         {
  328.             if (ptr == x.getPtr()) return * this;
  329.             decrement();
  330.             ptr = x.ptr;
  331.             count = x.count;
  332.             mutex = x.mutex;
  333.             increment();
  334.             return *this;
  335.         }
  336. /// compare whether a pointer and a smart pointer point to different things
  337.         friend bool operator!=(const void* y, const Sptr& x)
  338.         {
  339.             if (x.ptr != y)
  340.                 return true;
  341.             else
  342.                 return false;
  343.         }
  344. /// compare whether a smart pointer and a pointer point to different things
  345.         friend bool operator!=(const Sptr& x, const void* y)
  346.         {
  347.             if (x.ptr != y)
  348.                 return true;
  349.             else
  350.                 return false;
  351.         }
  352. /// compare whether a pointer and a smart pointer point to the same thing
  353.         friend bool operator==(const void* y, const Sptr& x)
  354.         {
  355.             if (x.ptr == y)
  356.                 return true;
  357.             else
  358.                 return false;
  359.         }
  360. /// compare whether a smart pointer and a pointer point to the same thing
  361.         friend bool operator==(const Sptr& x, const void* y)
  362.         {
  363.             if (x.ptr == y)
  364.                 return true;
  365.             else
  366.                 return false;
  367.         }
  368. /// compare whether two smart pointers point to the same thing
  369.         bool operator==(const Sptr& x) const
  370.         {
  371.             if (x.ptr == ptr)
  372.                 return true;
  373.             else
  374.                 return false;
  375.         }
  376. /// compare whether two smart pointers point to different things
  377.         bool operator!=(const Sptr& x) const
  378.         {
  379.             if (x.ptr != ptr)
  380.                 return true;
  381.             else
  382.                 return false;
  383.         }
  384. /**
  385.    this interface is here because it may sometimes be
  386.    necessary.  DO NOT USE unless you must use it.
  387.    get the actual mutex of the smart pointer.
  388. */
  389.         VMutex* getMutex() const
  390.         {
  391.             return mutex;
  392.         }
  393. /**
  394.    this interface is here because it may sometimes be
  395.    necessary.  DO NOT USE unless you must use it.
  396.    get the value of the reference count of the smart pointer.
  397. */
  398.         int* getCount() const
  399.         {
  400.             return count;
  401.         }
  402. /**
  403.    this interface is here because it may sometimes be
  404.    necessary.  DO NOT USE unless you must use it.
  405.    get the pointer to which the smart pointer points.
  406. */
  407.         T* getPtr() const
  408.         {
  409.             return ptr;
  410.         }
  411. };
  412. #endif
  413. #endif