Field3D
RefCount.h
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------//
00002 
00003 /*
00004  * Copyright (c) 2009 Sony Pictures Imageworks Inc
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  *
00012  * Redistributions of source code must retain the above copyright
00013  * notice, this list of conditions and the following disclaimer.
00014  * Redistributions in binary form must reproduce the above copyright
00015  * notice, this list of conditions and the following disclaimer in the
00016  * documentation and/or other materials provided with the
00017  * distribution.  Neither the name of Sony Pictures Imageworks nor the
00018  * names of its contributors may be used to endorse or promote
00019  * products derived from this software without specific prior written
00020  * permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
00026  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00028  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00029  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00031  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00033  * OF THE POSSIBILITY OF SUCH DAMAGE.
00034  */
00035 
00036 //----------------------------------------------------------------------------//
00037 
00042 //----------------------------------------------------------------------------//
00043 
00044 #ifndef _INCLUDED_Field3D_REF_COUNT_H_
00045 #define _INCLUDED_Field3D_REF_COUNT_H_
00046 
00047 #define FIELD3D_USE_ATOMIC_COUNT
00048 
00049 //----------------------------------------------------------------------------//
00050 #include <boost/intrusive_ptr.hpp> 
00051 
00052 #ifdef FIELD3D_USE_ATOMIC_COUNT
00053 #include <boost/detail/atomic_count.hpp>
00054 #else
00055 #include <boost/thread/mutex.hpp>
00056 #endif
00057 
00058 #include <string.h>
00059 #include "Traits.h"
00060 #include "ns.h"
00061 
00062 FIELD3D_NAMESPACE_OPEN
00063 
00064 //----------------------------------------------------------------------------//
00065 // Field RTTI Replacement
00066 //----------------------------------------------------------------------------//
00067 
00068 #define DEFINE_CHECK_RTTI_CALL                    \
00069   virtual bool checkRTTI(const char *typenameStr) \
00070   { return matchRTTI(typenameStr); }              \
00071   
00072 #define DEFINE_MATCH_RTTI_CALL                        \
00073   bool matchRTTI(const char *typenameStr)             \
00074   {                                                   \
00075     if (strcmp(typenameStr,classType()) == 0) {       \
00076       return true;                                    \
00077     }                                                 \
00078     return base::matchRTTI(typenameStr);              \
00079   }                                                   \
00080 
00081 #define DEFINE_FIELD_RTTI_CONCRETE_CLASS        \
00082   DEFINE_CHECK_RTTI_CALL                        \
00083   DEFINE_MATCH_RTTI_CALL                        \
00084 
00085 #define DEFINE_FIELD_RTTI_ABSTRACT_CLASS        \
00086   DEFINE_MATCH_RTTI_CALL                        \
00087 
00088 //----------------------------------------------------------------------------//
00089 
00090 class RefBase 
00091 {
00092 public:
00093 
00094   // Typedefs ------------------------------------------------------------------
00095 
00096   typedef boost::intrusive_ptr<RefBase> Ptr;
00097 
00098   // Constructors --------------------------------------------------------------
00099 
00102 
00103   RefBase() 
00104     : m_counter(0) 
00105   {}
00106     
00108   RefBase(const RefBase&) 
00109     : m_counter(0) 
00110   {}
00111 
00113   RefBase& operator= (const RefBase&)
00114   { return *this; }
00115 
00117   virtual ~RefBase() 
00118   {}
00119 
00121 
00122   // Reference counting --------------------------------------------------------
00123 
00125   size_t refcnt() 
00126   { return m_counter; }
00127     
00129   void ref() const
00130   { 
00131 #ifndef FIELD3D_USE_ATOMIC_COUNT
00132     boost::mutex::scoped_lock lock(m_refMutex);
00133 #endif
00134     ++m_counter; 
00135   }
00136 
00138   void unref() const
00139   {
00140 #ifndef FIELD3D_USE_ATOMIC_COUNT
00141     boost::mutex::scoped_lock lock(m_refMutex);
00142 #endif
00143     --m_counter; 
00144     // since we use intrusive_pointer no need
00145     // to delete the object ourselves.
00146   }
00147   
00148   // RTTI replacement ----------------------------------------------------------
00149 
00158 
00159 
00160 
00163   virtual bool checkRTTI(const char *typenameStr) = 0;
00164   
00167   bool matchRTTI(const char *typenameStr)
00168   {
00169     if (strcmp(classType(), typenameStr) == 0)
00170       return true;
00171     return false;
00172   }
00173 
00174   static const char *classType()
00175   {
00176     return "RefBase";
00177   }
00178 
00180 
00181 private:
00182 
00184 #ifdef FIELD3D_USE_ATOMIC_COUNT
00185   mutable boost::detail::atomic_count m_counter;
00186 #else
00187   mutable long m_counter;
00189   mutable boost::mutex m_refMutex;     
00190 #endif
00191 
00192 };
00193 
00194 //----------------------------------------------------------------------------//
00195 // Intrusive Pointer reference counting 
00196 //----------------------------------------------------------------------------//
00197 
00198 inline void 
00199 intrusive_ptr_add_ref(RefBase* r)
00200 {
00201   r->ref();
00202 }
00203 
00204 //----------------------------------------------------------------------------//
00205 
00206 inline void
00207 intrusive_ptr_release(RefBase* r)
00208 {
00209   r->unref();
00210 
00211   if (r->refcnt() == 0)
00212     delete r;
00213 }
00214 
00215 //----------------------------------------------------------------------------//
00216 // field_dynamic_cast
00217 //----------------------------------------------------------------------------//
00218 
00222 template <class Field_T>
00223 typename Field_T::Ptr
00224 field_dynamic_cast(RefBase::Ptr field)
00225 {
00226   if (!field) 
00227     return NULL;
00228 
00229   const char *tgtTypeString =  Field_T::classType();
00230   
00231   if (field->checkRTTI(tgtTypeString)) {
00232     return static_cast<Field_T*>(field.get());
00233   } else {
00234     return NULL;
00235   }
00236 }
00237 
00238 //#define FIELD_DYNAMIC_CAST boost::dynamic_pointer_cast
00239 #define FIELD_DYNAMIC_CAST field_dynamic_cast
00240 
00241 //----------------------------------------------------------------------------//
00242 
00243 FIELD3D_NAMESPACE_HEADER_CLOSE
00244 
00245 //----------------------------------------------------------------------------//
00246 
00247 #endif // Include guard
00248