memory.hpp

Go to the documentation of this file.
00001 #ifndef S11N_NET_S11N_MEMORY_HPP_INCLUDED
00002 #define S11N_NET_S11N_MEMORY_HPP_INCLUDED 1
00003 
00004 #include <s11n.net/s11n/exception.hpp> // s11n_exception and friends
00005 
00006 namespace s11n {
00007 
00008     /**
00009        Calls s11n_traits<SerializableType>::cleanup_functor()(s).
00010 
00011        This function is declared as no-throw because of its
00012        logical role in the destruction process, and dtors are
00013        normally prohibited from throwing. Any exceptions caught by
00014        this function are silently ignored (a warning might go out
00015        to a debug channel, probably cerr, but don't rely on it).
00016 
00017        SerializableType requirements:
00018 
00019        - Must be a Serializable. Specifically, it must have an
00020        s11n_traits specialization installed.
00021 
00022        - s11n_traits<SerializableType>::cleanup_functor must be
00023        known to work properly for SerializableType. This is core
00024        to the whole cleanup functionality, which is core to
00025        protecting against leaks in the face of errors.
00026 
00027        Technically, if the type can be delete()d without leaking
00028        pointers, it's safe for use with this function, but this
00029        function SHOULD NOT be used as general cleanup tool. It is
00030        ONLY intended to be used with REGISTERED Serializables.
00031 
00032        This function guarantees not to leak when "cleaning up"
00033        containers holding unmanaged pointers as long as the
00034        associated cleanup_functors do their part. The model is
00035        such that once a cleanup_functor is in place for a given
00036        type, this function will inherently walk it and invoke the
00037        cleanup rules, which includes freeing any pointers along
00038        the way.
00039 
00040        Added in 1.1.3.
00041     */
00042     template <typename SerializableType>
00043     void cleanup_serializable( SerializableType & s ) throw();
00044 
00045     /**
00046        This overload provides cleanup handling for pointer
00047        types. This simplifies many algorithms over using
00048        s11n_traits<SerializableType>::cleanup_functor directly, as
00049        the algorithms do not need to care if they're using
00050        pointer-qualified types or not in order to clean them up
00051        properly.
00052 
00053        SerializableType requirements are as for the non-pointered
00054        variant of this function, plus:
00055 
00056        - delete aSerializableTypeInstance; must be well-formed and
00057        must neither throw nor invoke undefined behaviour.  (Did
00058        you realize that "neither" is an exception to English's
00059        "i-before-e" rule?)
00060 
00061        This function does nothing if s is null, otherwise it calls
00062        cleanup_serializable(*s), deletes s, then assigns it to 0.
00063 
00064        Postcondition: (0 == s)
00065 
00066        Added in 1.1.3.
00067     */
00068     template <typename SerializableType>
00069     void cleanup_serializable( SerializableType * & s ) throw();
00070 
00071 
00072         /**
00073        Intended for use with for_each(), this type cleans up
00074        Serializables using cleanup_serializable().
00075 
00076        Usage:
00077 
00078        std::for_each( container.begin(), container.end(), cleaner_upper() );
00079 
00080        where the container is parameterized to hold Serializables.
00081 
00082        Provided that the contained type(s) conform to
00083        cleanup_ptr's requirements, this will recursively clean up
00084        sub-sub-...subcontainers.
00085 
00086        Note that Serializable containers should have a cleanup
00087        functor installed as part of their registration, making
00088        this class unnecessary for most cases: simply calling
00089        cleanup_serializable() will recursively walk/clean such
00090        containers. The underlying cleanup algos might use this
00091        type, however (at least one of them does).
00092 
00093        Added in 1.1.3.
00094 
00095        This type is usable as a Finalizer for
00096        s11n::refcount::rcptr, by the way.
00097      */
00098         struct cleaner_upper
00099         {
00100                 /**
00101                    Calls cleanup_serializable<T>(t)
00102                 */
00103                 template <typename T>
00104                 void operator()( T & t ) throw()
00105                 {
00106                         cleanup_serializable<T>( t );
00107                 }
00108                 /**
00109                    Calls cleanup_serializable<T>(t).
00110                 */
00111                 template <typename T>
00112                 void operator()( T * & t ) throw()
00113                 {
00114                         cleanup_serializable<T>( t );
00115                 }
00116         };
00117 
00118 
00119     /**
00120        An auto_ptr-like type intended to simplify
00121        pointer/exception safety in some deserialization algorithms
00122        by providing a way to completely and safely destroy
00123        partially-deserialized objects.
00124 
00125        SerializableT must either have an explicit s11n_traits
00126        specialization installed or work properly with the default
00127        functor provided by s11n_traits::cleanup_functor.  In
00128        practice, this means that types which manage the memory of
00129        their contained pointers are safe to work with the default,
00130        whereas the cleanup of unmanaged child pointers (e.g., std
00131        containers) requires a proper specialization.
00132 
00133        Note that this type does not have copy/assignment ctors,
00134        due to the conventional constness of their right-hand
00135        sides: use the swap() or take() members to take over a
00136        pointer.
00137 
00138        Added in 1.1.3.
00139 
00140 
00141        To consider for 1.3.x: reimplement this type on top of
00142        rcptr so that we can get sane copy semantics.
00143     */
00144     template <typename SerializableT>
00145     struct cleanup_ptr
00146     {
00147     public:
00148         typedef SerializableT cleaned_type;
00149     private:
00150         cleaned_type * m_ptr;
00151         cleanup_ptr & operator=( const cleanup_ptr & ); // Not Implemented
00152         cleanup_ptr( const cleanup_ptr & ); // Not Implemented
00153         void cleanup() throw()
00154         {
00155             if( this->m_ptr )
00156             {
00157                 cleanup_serializable<cleaned_type>( this->m_ptr );
00158             }
00159         }
00160     public:
00161         /**
00162            Constructs an object pointing to nothing.
00163         */
00164         cleanup_ptr() throw() : m_ptr(0) 
00165         {
00166         }
00167         /**
00168            Transfers ownership of p to this object.
00169          */
00170         cleanup_ptr( cleaned_type * p ) throw() : m_ptr(p)
00171         {
00172         }
00173 
00174         /**
00175            Uses s11n::cleanup_serializable<cleaned_type>()
00176            to free up up this->get().
00177         */
00178         ~cleanup_ptr() throw()
00179         {
00180             this->cleanup();
00181         }
00182         /**
00183            Dereferences this object's pointed-to object.  If
00184            this object does not point to anything it throws a
00185            std::runtime_error with an informative what()
00186            message explaining the error.
00187          */
00188         cleaned_type & operator*()
00189         {
00190             if( ! this->m_ptr )
00191             {
00192                 throw s11n_exception( S11N_SOURCEINFO,
00193                               "Attempt to dereference a null pointer via s11n::cleanup_ptr<>::operator*()" );
00194             }
00195             return *this->m_ptr;
00196         }
00197 
00198         /**
00199            Returns the same as get().
00200         */
00201         cleaned_type * operator->() throw()
00202         {
00203             return this->m_ptr;
00204         }
00205 
00206         /**
00207            Returns this object's pointed-to object without
00208            transfering ownership.
00209         */
00210         cleaned_type * get() throw()
00211         {
00212             return this->m_ptr;
00213         }
00214 
00215         /**
00216            Transfers ownership of p to this object. This
00217            member takes the place of copy/assign operators,
00218            since those conventionally take a const right-hand
00219            argument.
00220 
00221            Destroys the object this object pointed to before
00222            taking over ownership. 0 is a legal value for p.
00223 
00224            If (p == this->get()) then this function does
00225            nothing.
00226 
00227            Postcondition: p == this->get() 
00228         */
00229         void take( cleaned_type * p ) throw()
00230         {
00231             if( p != this->m_ptr )
00232             {
00233                 this->cleanup();
00234                 this->m_ptr = p;
00235             }
00236         }
00237 
00238         /**
00239            Transfers ownership of this->get() to the
00240            caller.
00241 
00242            Postcondition: 0 == this->get() 
00243         */
00244         cleaned_type * release() throw()
00245         {
00246             cleaned_type * x = this->m_ptr;
00247             this->m_ptr = 0;
00248             return x;
00249         }
00250 
00251         /**
00252            Cleans up any pointed-to object and points this
00253            object at 0. Does nothing if this object points
00254            to no object.
00255 
00256            Postcondition: 0 == this->get() 
00257         */
00258         void clean() throw()
00259         {
00260             this->take( 0 );
00261         }
00262 
00263         /**
00264            Swaps ownership of pointers with rhs.
00265         */
00266         void swap( cleanup_ptr & rhs ) throw()
00267         {
00268             cleaned_type * x = this->m_ptr;
00269             this->m_ptr = rhs.m_ptr;
00270             rhs.m_ptr = x;
00271         }
00272 
00273         /**
00274            Returns the same as (!this->get()).
00275         */
00276         bool empty() const throw()
00277         {
00278             return 0 == this->m_ptr;
00279         }
00280     };
00281 
00282     namespace Detail {
00283     /**
00284        We use a custom auto_ptr<> work-alike in place of
00285        std::auto_ptr so that s11n compiles cleanly under C++0x,
00286        where auto_ptr is apparently deprecated.
00287 
00288        This type is a subset of std::auto_ptr, the main difference being
00289        that it's not copyable.
00290 
00291        Note that this type is functionally very different from
00292        s11n::cleanup_ptr, which specifically handles the details
00293        of cleaning up Serializables, whereas this type simply uses
00294        delete to destroy its contents.
00295     */
00296     template <typename T>
00297         struct auto_ptr {
00298         auto_ptr( T * t ) : m_x(t) {}
00299         ~auto_ptr() { delete m_x; }
00300         T * get() const { return m_x; }
00301         T * release() { T * x = m_x; m_x = 0; return x; }
00302         T * operator->() const { return m_x; }
00303         void reset( T * x )
00304         {
00305             if( x != m_x ) delete m_x;
00306             m_x = x;
00307         }
00308         /** Throws if !this->get(). */
00309         T & operator*() const
00310         {
00311             if( ! m_x ) throw s11n_exception( S11N_SOURCEINFO,
00312                               "Attempt to dereference a null pointer via s11n::Detail::auto_ptr<>::operator*()" );
00313             return *m_x;
00314         }
00315         private:
00316         T * m_x;
00317         auto_ptr( auto_ptr const & );
00318         auto_ptr & operator=(auto_ptr const &);
00319         };
00320 
00321     } // namespace Detail
00322 } // namespace s11n
00323 #include <s11n.net/s11n/memory.tpp>
00324 #endif // S11N_NET_S11N_MEMORY_HPP_INCLUDED

Generated on Wed Jun 4 21:44:19 2008 for libs11n by  doxygen 1.5.3