shptr.hpp

См. документацию.
00001 /*
00002 
00003 Copyright (c) 2002-2005, Yauheni Akhotnikau
00004 All rights reserved.
00005 
00006 Redistribution and use in source and binary forms, with or without
00007 modification, are permitted provided that the following conditions are met:
00008 
00009 - Redistributions of source code must retain the above copyright notice, this
00010 list of conditions and the following disclaimer.
00011 
00012 - Redistributions in binary form must reproduce the above copyright notice, this
00013 list of conditions and the following disclaimer in the documentation and/or
00014 other materials provided with the distribution.
00015 
00016 - The name of the author may not be used to endorse or promote products derived
00017 from this software without specific prior written permission.
00018 
00019 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
00020 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00021 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
00022 EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00023 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00024 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00027 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
00028 OF SUCH DAMAGE.
00029 
00030 */
00031 
00037 #if !defined( _OESS_1__STDSN__SHPTR_HPP_ )
00038 #define _OESS_1__STDSN__SHPTR_HPP_
00039 
00040 #include <memory>
00041 
00042 #include <oess_1/defs/h/ex.hpp>
00043 
00044 #include <oess_1/stdsn/h/declspec.hpp>
00045 
00046 #include <oess_1/stdsn/h/serializable.hpp>
00047 #include <oess_1/stdsn/h/errno.hpp>
00048 
00049 namespace oess_1 {
00050 
00051 namespace stdsn {
00052 
00062 template< class T >
00063 class refcountable_policy_t
00064   : private cpp_util_2::nocopy_t
00065   {
00066   private :
00068     typedef unsigned long ref_count_t;
00069 
00071     ref_count_t * m_ref_count;
00072 
00074     T * & m_pointer_holder;
00075 
00076   public :
00078 
00081     explicit refcountable_policy_t( T * & pointer_holder )
00082       : m_ref_count( 0 )
00083       , m_pointer_holder( pointer_holder )
00084       {
00085         m_pointer_holder = 0;
00086       }
00087 
00089 
00093     refcountable_policy_t(
00094       T * & pointer_holder, T * pointer )
00095       : m_ref_count( 0 )
00096       , m_pointer_holder( pointer_holder )
00097       {
00098         assign( pointer );
00099       }
00100 
00106     ~refcountable_policy_t()
00107       {
00108         release();
00109       }
00110 
00112 
00116     void
00117     assign( T * ptr )
00118       {
00119         release();
00120 
00121         if( ptr )
00122           {
00123             m_ref_count = new ref_count_t( 1 );
00124             m_pointer_holder = ptr;
00125           }
00126       }
00127 
00129 
00134     void
00135     reassign()
00136       {
00137         // Счетчик ссылок должен быть нулевым!
00138         if( m_ref_count )
00139           OESS_THROW_PHYSIC(
00140               err::c_invalid_policy_state_for_reassignment,
00141               "reassignment when m_ref_count != null!" )
00142 
00143         m_ref_count = new ref_count_t( 1 );
00144       }
00145 
00147 
00149     void
00150     link(
00153       const refcountable_policy_t< T > & owner_policy )
00154       {
00155         if( &owner_policy != this )
00156           {
00157             release();
00158 
00159             if( 0 != ( m_ref_count = owner_policy.m_ref_count ) )
00160               {
00161                 ++( *m_ref_count );
00162                 m_pointer_holder = owner_policy.m_pointer_holder;
00163               }
00164           }
00165       }
00166 
00168 
00174     std::auto_ptr< T >
00175     release()
00176       {
00177         std::auto_ptr< T > result;
00178         if( m_ref_count )
00179           {
00180             if( 0 == ( --(*m_ref_count) ) )
00181               {
00182                 ref_count_t * to_be_destroyed = m_ref_count;
00183                 m_ref_count = 0;
00184 
00185                 delete to_be_destroyed;
00186 
00187                 result = std::auto_ptr< T >( m_pointer_holder );
00188                 m_pointer_holder = 0;
00189               }
00190             else
00191               // Кто-то другой уничтожит m_ref_count.
00192               m_ref_count = 0;
00193           }
00194 
00195         return result;
00196       }
00197   };
00198 
00220 template< class T >
00221 class cloneable_policy_t
00222   : private cpp_util_2::nocopy_t
00223   {
00224   private :
00226     T * & m_pointer_holder;
00227 
00228   public :
00230     explicit cloneable_policy_t( T * & pointer_holder )
00231       : m_pointer_holder( pointer_holder )
00232       {
00233         m_pointer_holder = 0;
00234       }
00235 
00237 
00241     cloneable_policy_t(
00242       T * & pointer_holder, T * pointer )
00243       : m_pointer_holder( pointer_holder )
00244       {
00245         m_pointer_holder = 0;
00246         assign( pointer );
00247       }
00248 
00254     ~cloneable_policy_t()
00255       {
00256         release();
00257       }
00258 
00260 
00264     void
00265     assign( T * ptr )
00266       {
00267         release();
00268 
00269         m_pointer_holder = ptr;
00270       }
00271 
00273 
00282     void
00283     reassign()
00284       {
00285       }
00286 
00288 
00292     void
00293     link(
00296       const cloneable_policy_t< T > & owner_policy )
00297       {
00298         if( &owner_policy != this )
00299           {
00300             release();
00301 
00302             if( owner_policy.m_pointer_holder )
00303               {
00304                 std::auto_ptr< T > clone(
00305                     owner_policy.m_pointer_holder->clone() );
00306                 m_pointer_holder = clone.release();
00307               }
00308           }
00309       }
00310 
00312 
00316     std::auto_ptr< T >
00317     release()
00318       {
00319         std::auto_ptr< T > result( m_pointer_holder );
00320         m_pointer_holder = 0;
00321 
00322         return result;
00323       }
00324   };
00325 
00334 template< class T >
00335 struct shptr_type_tag {};
00336 
00353 template<
00354     class T,
00355     class Own_policy = refcountable_policy_t< T > >
00356 class shptr_skeleton_t
00357   : public oess_1::stdsn::serializable_t
00358   {
00359     typedef shptr_skeleton_t< T, Own_policy > self_type_t;
00360 
00361   protected :
00363     T * m_ptr;
00364 
00365   private :
00367     Own_policy  m_own_policy;
00368 
00369   public :
00371 
00374     shptr_skeleton_t()
00375       : m_ptr( 0 )
00376       , m_own_policy( m_ptr )
00377       {}
00378 
00380     shptr_skeleton_t(
00384       T * ptr )
00385       : m_ptr( 0 )
00386       , m_own_policy( m_ptr, ptr )
00387       {}
00388 
00390     shptr_skeleton_t(
00391       const self_type_t & o )
00392       : m_ptr( 0 )
00393       , m_own_policy( m_ptr )
00394       {
00395         (*this) = o;
00396       }
00397     virtual ~shptr_skeleton_t()
00398       {}
00399 
00401     self_type_t &
00402     operator=(
00403       const self_type_t & o )
00404       {
00405         m_own_policy.link( o.m_own_policy );
00406         return *this;
00407       }
00408 
00410 
00411     virtual void
00412     oess_pack( oess_1::stdsn::oent_t & writter ) const = 0;
00413 
00414     virtual void
00415     oess_unpack( oess_1::stdsn::ient_t & reader ) = 0;
00416 
00417     virtual void *
00418     oess_cast( const std::string & type_name ) = 0;
00419 
00420     virtual const std::string &
00421     oess_type_name() const = 0;
00422 
00423     virtual const std::string &
00424     oess_scheme() const = 0;
00425 
00426     virtual void
00427     oess_get_subclass_extension_path(
00428       oess_1::stdsn::subclass_extension_path_t & path,
00429       const std::string & terminator ) const = 0;
00433 
00434 
00441     template< class Y >
00442     Y *
00443     cast_to( const shptr_type_tag< Y > & )
00444       {
00445         typedef typename Y::oess_serializer_t serializer_t;
00446         if( m_ptr )
00447           {
00448             Y * p = reinterpret_cast< Y * >(
00449                 m_ptr->oess_cast( serializer_t::type_name() ) );
00450             if( !p )
00451               OESS_THROW_LOGIC( err::c_cast_failed,
00452                   "unable cast from '" << m_ptr->oess_type_name()
00453                   << "' to '" << serializer_t::type_name() )
00454             return p;
00455           }
00456 
00457         return 0;
00458       }
00459 
00461 
00468     template< class Y >
00469     const Y *
00470     cast_to( const shptr_type_tag< Y > & ) const
00471       {
00472         typedef typename Y::oess_serializer_t serializer_t;
00473         if( m_ptr )
00474           {
00475             const Y * p = reinterpret_cast< const Y * >(
00476                 m_ptr->oess_cast( serializer_t::type_name() ) );
00477             if( !p )
00478               OESS_THROW_LOGIC( err::c_cast_failed,
00479                   "unable cast from '" << m_ptr->oess_type_name()
00480                   << "' to '" << serializer_t::type_name() )
00481             return p;
00482           }
00483 
00484         return 0;
00485       }
00488 
00489 
00490 
00491 
00496     void *
00497     cast_to( const std::string & type_name )
00498       {
00499         if( m_ptr )
00500           return m_ptr->oess_cast( type_name );
00501         return 0;
00502       }
00503 
00505 
00510     const void *
00511     cast_to( const std::string & type_name ) const
00512       {
00513         if( m_ptr )
00514           return m_ptr->oess_cast( type_name );
00515         return 0;
00516       }
00517 
00519 
00520 
00529     void
00530     destroy()
00531       {
00532         m_own_policy.release();
00533       }
00534 
00535   protected :
00540     virtual void
00541     oess_pre_unpack()
00542       {
00543         // После десериализации m_ptr примет новое значение.
00544         // Поэтому старый контролируемый объект должен быть
00545         // уничтожен.
00546         destroy();
00547       }
00548 
00553     virtual void
00554     oess_post_unpack()
00555       {
00556         m_own_policy.reassign();
00557       }
00558 
00561     Own_policy &
00562     own_policy()
00563       {
00564         return m_own_policy;
00565       }
00566 
00567     const Own_policy &
00568     own_policy() const 
00569       {
00570         return m_own_policy;
00571       }
00573   };
00574 
00575 //
00576 // shptr_t
00577 //
00578 
00616 class OESS_1__STDSN__TYPE shptr_t
00617   : public shptr_skeleton_t< oess_1::stdsn::serializable_t >
00618   {
00619   typedef shptr_skeleton_t< oess_1::stdsn::serializable_t > base_type_t;
00620   OESS_SERIALIZER_EX( shptr_t, OESS_1__STDSN__TYPE )
00621   public :
00623 
00626     shptr_t();
00628     shptr_t(
00632       serializable_t * ptr );
00634     shptr_t(
00635       const shptr_t & o );
00636     virtual ~shptr_t();
00637 
00639 
00643     shptr_t &
00644     operator=( const shptr_t & o );
00645 
00646   protected :
00649 
00650 
00657     virtual void
00658     oess_shptr_assign(
00659       const shptr_t & o );
00660 
00662 
00676     void
00677     oess_reset(
00679       serializable_t * ptr = 0 );
00681 };
00682 
00684 
00882 #define OESS_1_SHPTR_IFACE(shptr_type, referred_type, base_type) \
00883 private : \
00884   typedef base_type base_type_typedef__; \
00885   typedef base_type base_type_t; \
00886 public : \
00887   shptr_type() {} \
00888   shptr_type( referred_type * p ) : base_type_typedef__( p ) {} \
00889   shptr_type( const shptr_type & o ) : base_type_typedef__( o ) {} \
00890   virtual ~shptr_type() {} \
00891   shptr_type & \
00892   operator=( const shptr_type & o ) \
00893   { base_type_typedef__::operator=( o ); return *this; } \
00894   referred_type * \
00895   get() { return cast_to( oess_1::stdsn::shptr_type_tag< referred_type >() ); } \
00896   const referred_type * \
00897   get() const { return cast_to( oess_1::stdsn::shptr_type_tag< referred_type >() ); } \
00898   referred_type * \
00899   operator->() { return get(); } \
00900   const referred_type * \
00901   operator->() const { return get(); } \
00902   referred_type & \
00903   operator*() { return *get(); } \
00904   const referred_type & \
00905   operator*() const { return *get(); } \
00906 private :
00907 
00908 } /* namespace stdsn */
00909 
00910 } /* namespace oess_1 */
00911 
00912 #endif

Документация по ObjESSty. Последние изменения: Fri Oct 13 18:35:36 2006. Создано системой  doxygen 1.4.7
Hosted by uCoz