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 ///////////////////////////////////////////////////////////////////
69 * Don't forgett to provide versions for _Ptr and _constPtr,
70 * esp. if creation a of temporary is not acceptable (eg. when
71 * checking the ref count value).
73 namespace rw_pointer {
78 typedef shared_ptr<_D> _Ptr;
79 typedef shared_ptr<const _D> _constPtr;
80 /** Check whether pointer is not shared. */
81 bool unique( const _constPtr & ptr_r )
82 { return ptr_r.unique(); }
83 bool unique( const _Ptr & ptr_r )
84 { return ptr_r.unique(); }
85 /** Return number of references. */
86 long use_count( const _constPtr & ptr_r ) const
87 { return ptr_r.use_count(); }
88 long use_count( const _Ptr & ptr_r ) const
89 { return ptr_r.use_count(); }
95 typedef intrusive_ptr<_D> _Ptr;
96 typedef intrusive_ptr<const _D> _constPtr;
97 /** Check whether pointer is not shared. */
98 bool unique( const _constPtr & ptr_r )
99 { return !ptr_r || (ptr_r->refCount() <= 1); }
100 bool unique( const _Ptr & ptr_r )
101 { return !ptr_r || (ptr_r->refCount() <= 1); }
102 /** Return number of references. */
103 long use_count( const _constPtr & ptr_r ) const
104 { return ptr_r ? ptr_r->refCount() : 0; }
105 long use_count( const _Ptr & ptr_r ) const
106 { return ptr_r ? ptr_r->refCount() : 0; }
109 ///////////////////////////////////////////////////////////////////
111 ///////////////////////////////////////////////////////////////////
113 // CLASS NAME : RW_pointer
115 /** Wrapper for \c const correct access via \ref ZYPP_SMART_PTR.
117 * zypp::RW_pointer<tt>\<_D,_Traits></tt> stores a \ref ZYPP_SMART_PTR
118 * of type \c _Traits::_Ptr, which must be convertible into a <tt>_D *</tt>.
119 * Pointer style access (via \c -> and \c *) offers a <tt>const _D *</tt> in const
120 * a context, otherwise a <tt>_D *</tt>. Thus \em RW_ means \em read/write,
121 * as you get a different type, dependent on whether you're allowed to
124 * Forwarding access from an interface to an implemantation class, an
125 * RW_pointer prevents const interface methods from accidentally calling
126 * nonconst implementation methods.
128 * The second template argument defaults to
129 * <tt>_Traits = rw_pointer::Shared<_D></tt> thus wraping a
130 * <tt>shared_ptr<_D></tt>. To wrap an <tt>intrusive_ptr<_D></tt>
131 * use <tt>rw_pointer::Intrusive<_D></tt>.
133 * \see zypp::RWCOW_pointer for 'copy on write' functionality.
136 * #include "zypp/base/PtrTypes.h"
142 * // Implementation class
144 * // Pointer to implementation; actually a shared_ptr<Impl>
145 * RW_pointer<Impl> _pimpl;
147 * void baa() { _pimpl->... } // is Impl *
148 * void baa() const { _pimpl->... } // is Impl const *
152 template<class _D, class _Traits = rw_pointer::Shared<_D> >
155 typedef typename _Traits::_Ptr _Ptr;
156 typedef typename _Traits::_constPtr _constPtr;
157 typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
160 RW_pointer( typename _Ptr::element_type * dptr = 0 )
165 RW_pointer( _Ptr dptr )
170 { _Ptr().swap( _dptr ); }
172 void reset( typename _Ptr::element_type * dptr )
173 { _Ptr( dptr ).swap( _dptr ); }
175 void swap( RW_pointer & rhs )
176 { _dptr.swap( rhs._dptr ); }
178 void swap( _Ptr & rhs )
179 { _dptr.swap( rhs ); }
181 operator unspecified_bool_type() const
184 const _D & operator*() const
187 const _D * operator->() const
188 { return _dptr.get(); }
190 const _D * get() const
191 { return _dptr.get(); }
197 { return _dptr.get(); }
200 { return _dptr.get(); }
204 { return _Traits().unique( _dptr ); }
206 long use_count() const
207 { return _Traits().use_count( _dptr ); }
209 _constPtr getPtr() const
218 ///////////////////////////////////////////////////////////////////
220 /** \relates RW_pointer Stream output.
222 * Print the \c _D object the RW_pointer refers, or \c "NULL"
223 * if the pointer is \c NULL.
225 template<class _D, class _Ptr>
226 inline std::ostream &
227 operator<<( std::ostream & str, const RW_pointer<_D, _Ptr> & obj )
230 return str << *obj.get();
231 return str << std::string("NULL");
234 ///////////////////////////////////////////////////////////////////
236 ///////////////////////////////////////////////////////////////////
238 // CLASS NAME : RWCOW_pointer
240 /** \ref RW_pointer supporting 'copy on write' functionality.
242 * \em Write access to the underlying object creates a copy, iff
243 * the object is shared.
245 * See \ref RW_pointer.
247 template<class _D, class _Traits = rw_pointer::Shared<_D> >
250 typedef typename _Traits::_Ptr _Ptr;
251 typedef typename _Traits::_constPtr _constPtr;
252 typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
255 RWCOW_pointer( typename _Ptr::element_type * dptr = 0 )
260 RWCOW_pointer( _Ptr dptr )
265 { _Ptr().swap( _dptr ); }
267 void reset( typename _Ptr::element_type * dptr )
268 { _Ptr( dptr ).swap( _dptr ); }
270 void swap( RWCOW_pointer & rhs )
271 { _dptr.swap( rhs._dptr ); }
273 void swap( _Ptr & rhs )
274 { _dptr.swap( rhs ); }
276 operator unspecified_bool_type() const
279 const _D & operator*() const
282 const _D * operator->() const
283 { return _dptr.get(); }
285 const _D * get() const
286 { return _dptr.get(); }
289 { assertUnshared(); return *_dptr; }
292 { assertUnshared(); return _dptr.get(); }
295 { assertUnshared(); return _dptr.get(); }
299 { return _Traits().unique( _dptr ); }
301 long use_count() const
302 { return _Traits().use_count( _dptr ); }
304 _constPtr getPtr() const
308 { assertUnshared(); return _dptr; }
312 void assertUnshared()
315 _Ptr( rwcowClone( _dptr.get() ) ).swap( _dptr );
321 ///////////////////////////////////////////////////////////////////
323 /** \relates RWCOW_pointer Clone the underlying object.
324 * Calls \a rhs <tt>-\>clone()</tt>. Being defined as a
325 * function outside \ref RWCOW_pointer allows to overload
326 * it, in case a specific \a _D does not have <tt>clone()</tt>.
329 inline _D * rwcowClone( const _D * rhs )
330 { return rhs->clone(); }
332 ///////////////////////////////////////////////////////////////////
334 /** \relates RWCOW_pointer Stream output.
336 * Print the \c _D object the RWCOW_pointer refers, or \c "NULL"
337 * if the pointer is \c NULL.
339 template<class _D, class _Ptr>
340 inline std::ostream &
341 operator<<( std::ostream & str, const RWCOW_pointer<_D, _Ptr> & obj )
344 return str << *obj.get();
345 return str << std::string("NULL");
348 ///////////////////////////////////////////////////////////////////
352 /////////////////////////////////////////////////////////////////
354 ///////////////////////////////////////////////////////////////////
356 /** Forward declaration of Ptr types */
357 #define DEFINE_PTR_TYPE(NAME) \
359 extern void intrusive_ptr_add_ref( const NAME * ); \
360 extern void intrusive_ptr_release( const NAME * ); \
361 typedef zypp::intrusive_ptr<NAME> NAME##_Ptr; \
362 typedef zypp::intrusive_ptr<const NAME> NAME##_constPtr;
364 ///////////////////////////////////////////////////////////////////
365 #endif // ZYPP_BASE_PTRTYPES_H