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 /** shared_ptr custom deleter doing nothing.
45 * A custom deleter is a function being called when the
46 * last shared_ptr goes out of score. Per default the
47 * object gets deleted, but you can insall custom deleters
48 * as well. This one does nothing.
51 * // Some class providing a std::istream
54 * // Per deafult use std::cin.
56 * : _stream( &std::cin, NullDeleter() )
58 * // Or read from a file.
59 * InputStream( const Pathname & file_r )
60 * : _stream( new ifgzstream( _path.asString().c_str() ) )
62 * // Or use a stream priovided by the application.
63 * InputStream( std::istream & stream_r )
64 * : _stream( &stream_r, NullDeleter() )
67 * std::istream & stream()
68 * { return *_stream; }
71 * shared_ptr<std::istream> _stream;
77 void operator()( const void *const ) const
81 /** \class scoped_ptr */
82 using boost::scoped_ptr;
84 /** \class shared_ptr */
85 using boost::shared_ptr;
87 /** \class weak_ptr */
88 using boost::weak_ptr;
90 /** \class intrusive_ptr */
91 using boost::intrusive_ptr;
94 using boost::static_pointer_cast;
96 using boost::const_pointer_cast;
98 using boost::dynamic_pointer_cast;
100 /** \relates shared_ptr Stream output. */
102 inline std::ostream &
103 operator<<( std::ostream & str, const shared_ptr<_D> & obj )
107 return str << std::string("NULL");
110 /** \relates intrusive_ptr Stream output. */
112 inline std::ostream &
113 operator<<( std::ostream & str, const intrusive_ptr<_D> & obj )
117 return str << std::string("NULL");
120 ///////////////////////////////////////////////////////////////////
124 ///////////////////////////////////////////////////////////////////
126 * Don't forgett to provide versions for _Ptr and _constPtr,
127 * esp. if creation a of temporary is not acceptable (eg. when
128 * checking the ref count value).
130 namespace rw_pointer {
135 typedef shared_ptr<_D> _Ptr;
136 typedef shared_ptr<const _D> _constPtr;
137 /** Check whether pointer is not shared. */
138 bool unique( const _constPtr & ptr_r )
139 { return !ptr_r || ptr_r.unique(); }
140 bool unique( const _Ptr & ptr_r )
141 { return !ptr_r || ptr_r.unique(); }
142 /** Return number of references. */
143 long use_count( const _constPtr & ptr_r ) const
144 { return ptr_r.use_count(); }
145 long use_count( const _Ptr & ptr_r ) const
146 { return ptr_r.use_count(); }
152 typedef intrusive_ptr<_D> _Ptr;
153 typedef intrusive_ptr<const _D> _constPtr;
154 /** Check whether pointer is not shared. */
155 bool unique( const _constPtr & ptr_r )
156 { return !ptr_r || (ptr_r->refCount() <= 1); }
157 bool unique( const _Ptr & ptr_r )
158 { return !ptr_r || (ptr_r->refCount() <= 1); }
159 /** Return number of references. */
160 long use_count( const _constPtr & ptr_r ) const
161 { return ptr_r ? ptr_r->refCount() : 0; }
162 long use_count( const _Ptr & ptr_r ) const
163 { return ptr_r ? ptr_r->refCount() : 0; }
166 ///////////////////////////////////////////////////////////////////
168 ///////////////////////////////////////////////////////////////////
170 // CLASS NAME : RW_pointer
172 /** Wrapper for \c const correct access via \ref ZYPP_SMART_PTR.
174 * zypp::RW_pointer<tt>\<_D,_Traits></tt> stores a \ref ZYPP_SMART_PTR
175 * of type \c _Traits::_Ptr, which must be convertible into a <tt>_D *</tt>.
176 * Pointer style access (via \c -> and \c *) offers a <tt>const _D *</tt> in const
177 * a context, otherwise a <tt>_D *</tt>. Thus \em RW_ means \em read/write,
178 * as you get a different type, dependent on whether you're allowed to
181 * Forwarding access from an interface to an implemantation class, an
182 * RW_pointer prevents const interface methods from accidentally calling
183 * nonconst implementation methods.
185 * The second template argument defaults to
186 * <tt>_Traits = rw_pointer::Shared<_D></tt> thus wraping a
187 * <tt>shared_ptr<_D></tt>. To wrap an <tt>intrusive_ptr<_D></tt>
188 * use <tt>rw_pointer::Intrusive<_D></tt>.
190 * \see zypp::RWCOW_pointer for 'copy on write' functionality.
193 * #include "zypp/base/PtrTypes.h"
199 * // Implementation class
201 * // Pointer to implementation; actually a shared_ptr<Impl>
202 * RW_pointer<Impl> _pimpl;
204 * void baa() { _pimpl->... } // is Impl *
205 * void baa() const { _pimpl->... } // is Impl const *
209 template<class _D, class _Traits = rw_pointer::Shared<_D> >
212 typedef typename _Traits::_Ptr _Ptr;
213 typedef typename _Traits::_constPtr _constPtr;
214 typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
217 RW_pointer( typename _Ptr::element_type * dptr = 0 )
222 RW_pointer( _Ptr dptr )
227 { _Ptr().swap( _dptr ); }
229 void reset( typename _Ptr::element_type * dptr )
230 { _Ptr( dptr ).swap( _dptr ); }
232 void swap( RW_pointer & rhs )
233 { _dptr.swap( rhs._dptr ); }
235 void swap( _Ptr & rhs )
236 { _dptr.swap( rhs ); }
238 operator unspecified_bool_type() const
241 const _D & operator*() const
244 const _D * operator->() const
245 { return _dptr.get(); }
247 const _D * get() const
248 { return _dptr.get(); }
254 { return _dptr.get(); }
257 { return _dptr.get(); }
261 { return _Traits().unique( _dptr ); }
263 long use_count() const
264 { return _Traits().use_count( _dptr ); }
266 _constPtr getPtr() const
275 ///////////////////////////////////////////////////////////////////
277 /** \relates RW_pointer Stream output.
279 * Print the \c _D object the RW_pointer refers, or \c "NULL"
280 * if the pointer is \c NULL.
282 template<class _D, class _Ptr>
283 inline std::ostream &
284 operator<<( std::ostream & str, const RW_pointer<_D, _Ptr> & obj )
287 return str << *obj.get();
288 return str << std::string("NULL");
291 ///////////////////////////////////////////////////////////////////
293 ///////////////////////////////////////////////////////////////////
295 // CLASS NAME : RWCOW_pointer
297 /** \ref RW_pointer supporting 'copy on write' functionality.
299 * \em Write access to the underlying object creates a copy, iff
300 * the object is shared.
302 * See \ref RW_pointer.
304 template<class _D, class _Traits = rw_pointer::Shared<_D> >
307 typedef typename _Traits::_Ptr _Ptr;
308 typedef typename _Traits::_constPtr _constPtr;
309 typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
312 RWCOW_pointer( typename _Ptr::element_type * dptr = 0 )
317 RWCOW_pointer( _Ptr dptr )
322 { _Ptr().swap( _dptr ); }
324 void reset( typename _Ptr::element_type * dptr )
325 { _Ptr( dptr ).swap( _dptr ); }
327 void swap( RWCOW_pointer & rhs )
328 { _dptr.swap( rhs._dptr ); }
330 void swap( _Ptr & rhs )
331 { _dptr.swap( rhs ); }
333 operator unspecified_bool_type() const
336 const _D & operator*() const
339 const _D * operator->() const
340 { return _dptr.get(); }
342 const _D * get() const
343 { return _dptr.get(); }
346 { assertUnshared(); return *_dptr; }
349 { assertUnshared(); return _dptr.get(); }
352 { assertUnshared(); return _dptr.get(); }
356 { return _Traits().unique( _dptr ); }
358 long use_count() const
359 { return _Traits().use_count( _dptr ); }
361 _constPtr getPtr() const
365 { assertUnshared(); return _dptr; }
369 void assertUnshared()
372 _Ptr( rwcowClone( _dptr.get() ) ).swap( _dptr );
378 ///////////////////////////////////////////////////////////////////
380 /** \relates RWCOW_pointer Clone the underlying object.
381 * Calls \a rhs <tt>-\>clone()</tt>. Being defined as a
382 * function outside \ref RWCOW_pointer allows to overload
383 * it, in case a specific \a _D does not have <tt>clone()</tt>.
386 inline _D * rwcowClone( const _D * rhs )
387 { return rhs->clone(); }
389 ///////////////////////////////////////////////////////////////////
391 /** \relates RWCOW_pointer Stream output.
393 * Print the \c _D object the RWCOW_pointer refers, or \c "NULL"
394 * if the pointer is \c NULL.
396 template<class _D, class _Ptr>
397 inline std::ostream &
398 operator<<( std::ostream & str, const RWCOW_pointer<_D, _Ptr> & obj )
401 return str << *obj.get();
402 return str << std::string("NULL");
405 ///////////////////////////////////////////////////////////////////
409 /////////////////////////////////////////////////////////////////
411 ///////////////////////////////////////////////////////////////////
413 /** Forward declaration of Ptr types */
414 #define DEFINE_PTR_TYPE(NAME) \
416 extern void intrusive_ptr_add_ref( const NAME * ); \
417 extern void intrusive_ptr_release( const NAME * ); \
418 typedef zypp::intrusive_ptr<NAME> NAME##_Ptr; \
419 typedef zypp::intrusive_ptr<const NAME> NAME##_constPtr;
421 ///////////////////////////////////////////////////////////////////
422 #endif // ZYPP_BASE_PTRTYPES_H