1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/base/PtrTypes.h
10 * \ingroup ZYPP_SMART_PTR
13 #ifndef ZYPP_BASE_PTRTYPES_H
14 #define ZYPP_BASE_PTRTYPES_H
18 #include <boost/scoped_ptr.hpp>
19 #include <boost/shared_ptr.hpp>
20 #include <boost/weak_ptr.hpp>
21 #include <boost/intrusive_ptr.hpp>
23 ///////////////////////////////////////////////////////////////////
25 { /////////////////////////////////////////////////////////////////
27 /** \defgroup ZYPP_SMART_PTR Smart pointer types
28 * Smart pointer types.
30 * Namespace zypp provides 3 smart pointer types \b using the
31 * boost smart pointer library.
33 * \li \c scoped_ptr Simple sole ownership of single objects. Noncopyable.
35 * \li \c shared_ptr Object ownership shared among multiple pointers
37 * \li \c weak_ptr Non-owning observers of an object owned by shared_ptr.
39 * And \ref zypp::RW_pointer, as wrapper around a smart pointer,
40 * poviding \c const correct read/write access to the object it refers.
44 /** \class scoped_ptr scoped_ptr */
45 using boost::scoped_ptr;
47 /** \class shared_ptr */
48 using boost::shared_ptr;
50 /** \class weak_ptr */
51 using boost::weak_ptr;
53 /** \class intrusive_ptr */
54 using boost::intrusive_ptr;
57 using boost::static_pointer_cast;
59 using boost::const_pointer_cast;
61 using boost::dynamic_pointer_cast;
63 ///////////////////////////////////////////////////////////////////
67 ///////////////////////////////////////////////////////////////////
68 namespace rw_pointer {
73 typedef shared_ptr<_D> _Ptr;
74 typedef shared_ptr<const _D> _constPtr;
75 /** Check whether pointer is shared. */
76 bool isShared( const _constPtr & ptr_r )
77 { return ptr_r.use_count() > 1; }
83 typedef intrusive_ptr<_D> _Ptr;
84 typedef intrusive_ptr<const _D> _constPtr;
85 /** Check whether pointer is shared. */
86 bool isShared( const _constPtr & ptr_r )
87 { return ptr_r && (ptr_r->refCount() > 1); }
90 ///////////////////////////////////////////////////////////////////
92 ///////////////////////////////////////////////////////////////////
94 // CLASS NAME : RW_pointer
96 /** Wrapper for \c const correct access via \ref ZYPP_SMART_PTR.
98 * zypp::RW_pointer<tt>\<_D,_Traits></tt> stores a \ref ZYPP_SMART_PTR
99 * of type \c _Traits::_Ptr, which must be convertible into a <tt>_D *</tt>.
100 * Pointer style access (via \c -> and \c *) offers a <tt>const _D *</tt> in const
101 * a context, otherwise a <tt>_D *</tt>. Thus \em RW_ means \em read/write,
102 * as you get a different type, dependent on whether you're allowed to
105 * Forwarding access from an interface to an implemantation class, an
106 * RW_pointer prevents const interface methods from accidentally calling
107 * nonconst implementation methods.
109 * The second template argument defaults to
110 * <tt>_Traits = rw_pointer::Shared<_D></tt> thus wraping a
111 * <tt>shared_ptr<_D></tt>. To wrap an <tt>intrusive_ptr<_D></tt>
112 * use <tt>rw_pointer::Intrusive<_D></tt>.
114 * \see zypp::RWCOW_pointer for 'copy on write' functionality.
117 * #include "zypp/base/PtrTypes.h"
123 * // Implementation class
125 * // Pointer to implementation; actually a shared_ptr<Impl>
126 * RW_pointer<Impl> _pimpl;
128 * void baa() { _pimpl->... } // is Impl *
129 * void baa() const { _pimpl->... } // is Impl const *
133 template<class _D, class _Traits = rw_pointer::Shared<_D> >
136 typedef typename _Traits::_Ptr _Ptr;
137 typedef typename _Traits::_constPtr _constPtr;
138 typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
141 RW_pointer( typename _Ptr::element_type * dptr = 0 )
146 RW_pointer( _Ptr dptr )
153 void reset( typename _Ptr::element_type * dptr )
154 { _dptr.reset( dptr ); }
156 void swap( RW_pointer & rhs )
157 { _dptr.swap( rhs._dptr ); }
159 void swap( _Ptr & rhs )
160 { _dptr.swap( rhs ); }
162 operator unspecified_bool_type() const
165 const _D & operator*() const
168 const _D * operator->() const
169 { return _dptr.get(); }
171 const _D * get() const
172 { return _dptr.get(); }
178 { return _dptr.get(); }
181 { return _dptr.get(); }
185 { return _dptr.unique(); }
187 long use_count() const
188 { return _dptr.use_count(); }
190 _constPtr getPtr() const
199 ///////////////////////////////////////////////////////////////////
201 /** \relates RW_pointer Stream output.
203 * Print the \c _D object the RW_pointer refers, or \c "NULL"
204 * if the pointer is \c NULL.
206 template<class _D, class _Ptr>
207 inline std::ostream &
208 operator<<( std::ostream & str, const RW_pointer<_D, _Ptr> & obj )
211 return str << *obj.get();
212 return str << std::string("NULL");
215 ///////////////////////////////////////////////////////////////////
217 ///////////////////////////////////////////////////////////////////
219 // CLASS NAME : RWCOW_pointer
221 /** \ref RW_pointer supporting 'copy on write' functionality.
223 * \em Write access to the underlying object creates a copy, iff
224 * the object is shared.
226 * See \ref RW_pointer.
228 template<class _D, class _Traits = rw_pointer::Shared<_D> >
231 typedef typename _Traits::_Ptr _Ptr;
232 typedef typename _Traits::_constPtr _constPtr;
233 typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
236 RWCOW_pointer( typename _Ptr::element_type * dptr = 0 )
241 RWCOW_pointer( _Ptr dptr )
248 void reset( typename _Ptr::element_type * dptr )
249 { _dptr.reset( dptr ); }
251 void swap( RWCOW_pointer & rhs )
252 { _dptr.swap( rhs._dptr ); }
254 void swap( _Ptr & rhs )
255 { _dptr.swap( rhs ); }
257 operator unspecified_bool_type() const
260 const _D & operator*() const
263 const _D * operator->() const
264 { return _dptr.get(); }
266 const _D * get() const
267 { return _dptr.get(); }
270 { assertUnshared(); return *_dptr; }
273 { assertUnshared(); return _dptr.get(); }
276 { assertUnshared(); return _dptr.get(); }
279 _constPtr getPtr() const
283 { assertUnshared(); return _dptr; }
287 void assertUnshared()
289 if ( _Traits().isShared( _dptr ) )
291 _dptr.reset( rwcowClone( _dptr.get() ) );
298 ///////////////////////////////////////////////////////////////////
300 /** \relates RWCOW_pointer Clone the underlying object.
301 * Calls \a rhs <tt>-\>clone()</tt>. Being defined as a
302 * function outside \ref RWCOW_pointer allows to overload
303 * it, in case a specific \a _D does not have <tt>clone()</tt>.
306 inline _D * rwcowClone( const _D * rhs )
307 { return rhs->clone(); }
309 ///////////////////////////////////////////////////////////////////
311 /** \relates RWCOW_pointer Stream output.
313 * Print the \c _D object the RWCOW_pointer refers, or \c "NULL"
314 * if the pointer is \c NULL.
316 template<class _D, class _Ptr>
317 inline std::ostream &
318 operator<<( std::ostream & str, const RWCOW_pointer<_D, _Ptr> & obj )
321 return str << *obj.get();
322 return str << std::string("NULL");
325 ///////////////////////////////////////////////////////////////////
329 /////////////////////////////////////////////////////////////////
331 ///////////////////////////////////////////////////////////////////
333 /** Forward declaration of Ptr types */
334 #define DEFINE_PTR_TYPE(NAME) \
336 extern void intrusive_ptr_add_ref( const NAME * ); \
337 extern void intrusive_ptr_release( const NAME * ); \
338 typedef zypp::intrusive_ptr<NAME> NAME##_Ptr; \
339 typedef zypp::intrusive_ptr<const NAME> NAME##_constPtr;
341 ///////////////////////////////////////////////////////////////////
342 #endif // ZYPP_BASE_PTRTYPES_H