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 /////////////////////////////////////////////////////////////////
102 ///////////////////////////////////////////////////////////////////
103 ///////////////////////////////////////////////////////////////////
105 { /////////////////////////////////////////////////////////////////
109 // typedef zypp::intrusive_ptr<Foo> Foo_Ptr; // see DEFINE_PTR_TYPE(NAME) macro below
112 // Defined in namespace std g++ finds the output operator (König-Lookup),
113 // even if we typedef the pointer in a different namespace than ::zypp.
114 // Otherwise we had to define an output operator always in the same namespace
115 // as the typedef (else g++ will just print the pointer value).
117 /** \relates zypp::shared_ptr Stream output. */
119 inline std::ostream & operator<<( std::ostream & str, const zypp::shared_ptr<_D> & obj )
123 return str << std::string("NULL");
125 /** \relates zypp::shared_ptr Stream output. */
127 inline std::ostream & dumpOn( std::ostream & str, const zypp::shared_ptr<_D> & obj )
130 return dumpOn( str, *obj );
131 return str << std::string("NULL");
134 /** \relates zypp::intrusive_ptr Stream output. */
136 inline std::ostream & operator<<( std::ostream & str, const zypp::intrusive_ptr<_D> & obj )
140 return str << std::string("NULL");
142 /** \relates zypp::intrusive_ptr Stream output. */
144 inline std::ostream & dumpOn( std::ostream & str, const zypp::intrusive_ptr<_D> & obj )
147 return dumpOn( str, *obj );
148 return str << std::string("NULL");
150 /////////////////////////////////////////////////////////////////
152 ///////////////////////////////////////////////////////////////////
153 ///////////////////////////////////////////////////////////////////
155 { /////////////////////////////////////////////////////////////////
157 ///////////////////////////////////////////////////////////////////
161 ///////////////////////////////////////////////////////////////////
163 * Don't forgett to provide versions for _Ptr and _constPtr,
164 * esp. if creation a of temporary is not acceptable (eg. when
165 * checking the ref count value).
167 namespace rw_pointer {
172 typedef shared_ptr<_D> _Ptr;
173 typedef shared_ptr<const _D> _constPtr;
174 /** Check whether pointer is not shared. */
175 bool unique( const _constPtr & ptr_r )
176 { return !ptr_r || ptr_r.unique(); }
177 bool unique( const _Ptr & ptr_r )
178 { return !ptr_r || ptr_r.unique(); }
179 /** Return number of references. */
180 long use_count( const _constPtr & ptr_r ) const
181 { return ptr_r.use_count(); }
182 long use_count( const _Ptr & ptr_r ) const
183 { return ptr_r.use_count(); }
189 typedef intrusive_ptr<_D> _Ptr;
190 typedef intrusive_ptr<const _D> _constPtr;
191 /** Check whether pointer is not shared. */
192 bool unique( const _constPtr & ptr_r )
193 { return !ptr_r || (ptr_r->refCount() <= 1); }
194 bool unique( const _Ptr & ptr_r )
195 { return !ptr_r || (ptr_r->refCount() <= 1); }
196 /** Return number of references. */
197 long use_count( const _constPtr & ptr_r ) const
198 { return ptr_r ? ptr_r->refCount() : 0; }
199 long use_count( const _Ptr & ptr_r ) const
200 { return ptr_r ? ptr_r->refCount() : 0; }
206 typedef scoped_ptr<_D> _Ptr;
207 typedef scoped_ptr<const _D> _constPtr;
208 /** Check whether pointer is not shared. */
209 bool unique( const _constPtr & ptr_r )
211 bool unique( const _Ptr & ptr_r )
213 /** Return number of references. */
214 long use_count( const _constPtr & ptr_r ) const
215 { return ptr_r ? 1 : 0; }
216 long use_count( const _Ptr & ptr_r ) const
217 { return ptr_r ? 1 : 0; }
221 ///////////////////////////////////////////////////////////////////
223 ///////////////////////////////////////////////////////////////////
225 // CLASS NAME : RW_pointer
227 /** Wrapper for \c const correct access via \ref ZYPP_SMART_PTR.
229 * zypp::RW_pointer<tt>\<_D,_Traits></tt> stores a \ref ZYPP_SMART_PTR
230 * of type \c _Traits::_Ptr, which must be convertible into a <tt>_D *</tt>.
231 * Pointer style access (via \c -> and \c *) offers a <tt>const _D *</tt> in const
232 * a context, otherwise a <tt>_D *</tt>. Thus \em RW_ means \em read/write,
233 * as you get a different type, dependent on whether you're allowed to
236 * Forwarding access from an interface to an implemantation class, an
237 * RW_pointer prevents const interface methods from accidentally calling
238 * nonconst implementation methods.
240 * The second template argument defaults to
241 * <tt>_Traits = rw_pointer::Shared<_D></tt> thus wraping a
242 * <tt>shared_ptr<_D></tt>. To wrap an <tt>intrusive_ptr<_D></tt>
243 * use <tt>rw_pointer::Intrusive<_D></tt>.
245 * \see zypp::RWCOW_pointer for 'copy on write' functionality.
248 * #include "zypp/base/PtrTypes.h"
254 * // Implementation class
256 * // Pointer to implementation; actually a shared_ptr<Impl>
257 * RW_pointer<Impl> _pimpl;
259 * void baa() { _pimpl->... } // is Impl *
260 * void baa() const { _pimpl->... } // is Impl const *
264 template<class _D, class _Traits = rw_pointer::Shared<_D> >
267 typedef typename _Traits::_Ptr _Ptr;
268 typedef typename _Traits::_constPtr _constPtr;
269 typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
272 RW_pointer( typename _Ptr::element_type * dptr = 0 )
277 RW_pointer( _Ptr dptr )
282 { _Ptr().swap( _dptr ); }
284 void reset( typename _Ptr::element_type * dptr )
285 { _Ptr( dptr ).swap( _dptr ); }
287 void swap( RW_pointer & rhs )
288 { _dptr.swap( rhs._dptr ); }
290 void swap( _Ptr & rhs )
291 { _dptr.swap( rhs ); }
293 operator unspecified_bool_type() const
296 const _D & operator*() const
299 const _D * operator->() const
300 { return _dptr.get(); }
302 const _D * get() const
303 { return _dptr.get(); }
309 { return _dptr.get(); }
312 { return _dptr.get(); }
316 { return _Traits().unique( _dptr ); }
318 long use_count() const
319 { return _Traits().use_count( _dptr ); }
321 _constPtr getPtr() const
333 ///////////////////////////////////////////////////////////////////
335 /** \relates RW_pointer Stream output.
337 * Print the \c _D object the RW_pointer refers, or \c "NULL"
338 * if the pointer is \c NULL.
340 template<class _D, class _Ptr>
341 inline std::ostream & operator<<( std::ostream & str, const RW_pointer<_D, _Ptr> & obj )
344 return str << *obj.get();
345 return str << std::string("NULL");
348 /** \relates RW_pointer */
349 template<class _D, class _Ptr>
350 inline bool operator==( const RW_pointer<_D, _Ptr> & lhs, const RW_pointer<_D, _Ptr> & rhs )
351 { return( lhs.get() == rhs.get() ); }
352 /** \relates RW_pointer */
353 template<class _D, class _Ptr>
354 inline bool operator==( const RW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_Ptr & rhs )
355 { return( lhs.get() == rhs.get() ); }
356 /** \relates RW_pointer */
357 template<class _D, class _Ptr>
358 inline bool operator==( const typename _Ptr::_Ptr & lhs, const RW_pointer<_D, _Ptr> & rhs )
359 { return( lhs.get() == rhs.get() ); }
360 /** \relates RW_pointer */
361 template<class _D, class _Ptr>
362 inline bool operator==( const RW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_constPtr & rhs )
363 { return( lhs.get() == rhs.get() ); }
364 /** \relates RW_pointer */
365 template<class _D, class _Ptr>
366 inline bool operator==( const typename _Ptr::_constPtr & lhs, const RW_pointer<_D, _Ptr> & rhs )
367 { return( lhs.get() == rhs.get() ); }
370 /** \relates RW_pointer */
371 template<class _D, class _Ptr>
372 inline bool operator!=( const RW_pointer<_D, _Ptr> & lhs, const RW_pointer<_D, _Ptr> & rhs )
373 { return ! ( lhs == rhs ); }
374 /** \relates RW_pointer */
375 template<class _D, class _Ptr>
376 inline bool operator!=( const RW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_Ptr & rhs )
377 { return ! ( lhs == rhs ); }
378 /** \relates RW_pointer */
379 template<class _D, class _Ptr>
380 inline bool operator!=( const typename _Ptr::_Ptr & lhs, const RW_pointer<_D, _Ptr> & rhs )
381 { return ! ( lhs == rhs ); }
382 /** \relates RW_pointer */
383 template<class _D, class _Ptr>
384 inline bool operator!=( const RW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_constPtr & rhs )
385 { return ! ( lhs == rhs ); }
386 /** \relates RW_pointer */
387 template<class _D, class _Ptr>
388 inline bool operator!=( const typename _Ptr::_constPtr & lhs, const RW_pointer<_D, _Ptr> & rhs )
389 { return ! ( lhs == rhs ); }
391 ///////////////////////////////////////////////////////////////////
393 ///////////////////////////////////////////////////////////////////
395 // CLASS NAME : RWCOW_pointer
397 /** \ref RW_pointer supporting 'copy on write' functionality.
399 * \em Write access to the underlying object creates a copy, iff
400 * the object is shared.
402 * See \ref RW_pointer.
404 template<class _D, class _Traits = rw_pointer::Shared<_D> >
407 typedef typename _Traits::_Ptr _Ptr;
408 typedef typename _Traits::_constPtr _constPtr;
409 typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
412 RWCOW_pointer( typename _Ptr::element_type * dptr = 0 )
417 RWCOW_pointer( _Ptr dptr )
422 { _Ptr().swap( _dptr ); }
424 void reset( typename _Ptr::element_type * dptr )
425 { _Ptr( dptr ).swap( _dptr ); }
427 void swap( RWCOW_pointer & rhs )
428 { _dptr.swap( rhs._dptr ); }
430 void swap( _Ptr & rhs )
431 { _dptr.swap( rhs ); }
433 operator unspecified_bool_type() const
436 const _D & operator*() const
439 const _D * operator->() const
440 { return _dptr.get(); }
442 const _D * get() const
443 { return _dptr.get(); }
446 { assertUnshared(); return *_dptr; }
449 { assertUnshared(); return _dptr.get(); }
452 { assertUnshared(); return _dptr.get(); }
456 { return _Traits().unique( _dptr ); }
458 long use_count() const
459 { return _Traits().use_count( _dptr ); }
461 _constPtr getPtr() const
465 { assertUnshared(); return _dptr; }
472 void assertUnshared()
475 _Ptr( rwcowClone( _dptr.get() ) ).swap( _dptr );
481 ///////////////////////////////////////////////////////////////////
483 /** \relates RWCOW_pointer Clone the underlying object.
484 * Calls \a rhs <tt>-\>clone()</tt>. Being defined as a
485 * function outside \ref RWCOW_pointer allows to overload
486 * it, in case a specific \a _D does not have <tt>clone()</tt>.
489 inline _D * rwcowClone( const _D * rhs )
490 { return rhs->clone(); }
492 ///////////////////////////////////////////////////////////////////
494 /** \relates RWCOW_pointer Stream output.
496 * Print the \c _D object the RWCOW_pointer refers, or \c "NULL"
497 * if the pointer is \c NULL.
499 template<class _D, class _Ptr>
500 inline std::ostream & operator<<( std::ostream & str, const RWCOW_pointer<_D, _Ptr> & obj )
503 return str << *obj.get();
504 return str << std::string("NULL");
507 /** \relates RWCOW_pointer */
508 template<class _D, class _Ptr>
509 inline bool operator==( const RWCOW_pointer<_D, _Ptr> & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
510 { return( lhs.get() == rhs.get() ); }
511 /** \relates RWCOW_pointer */
512 template<class _D, class _Ptr>
513 inline bool operator==( const RWCOW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_Ptr & rhs )
514 { return( lhs.get() == rhs.get() ); }
515 /** \relates RWCOW_pointer */
516 template<class _D, class _Ptr>
517 inline bool operator==( const typename _Ptr::_Ptr & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
518 { return( lhs.get() == rhs.get() ); }
519 /** \relates RWCOW_pointer */
520 template<class _D, class _Ptr>
521 inline bool operator==( const RWCOW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_constPtr & rhs )
522 { return( lhs.get() == rhs.get() ); }
523 /** \relates RWCOW_pointer */
524 template<class _D, class _Ptr>
525 inline bool operator==( const typename _Ptr::_constPtr & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
526 { return( lhs.get() == rhs.get() ); }
528 /** \relates RWCOW_pointer */
529 template<class _D, class _Ptr>
530 inline bool operator!=( const RWCOW_pointer<_D, _Ptr> & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
531 { return ! ( lhs == rhs ); }
532 /** \relates RWCOW_pointer */
533 template<class _D, class _Ptr>
534 inline bool operator!=( const RWCOW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_Ptr & rhs )
535 { return ! ( lhs == rhs ); }
536 /** \relates RWCOW_pointer */
537 template<class _D, class _Ptr>
538 inline bool operator!=( const typename _Ptr::_Ptr & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
539 { return ! ( lhs == rhs ); }
540 /** \relates RWCOW_pointer */
541 template<class _D, class _Ptr>
542 inline bool operator!=( const RWCOW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_constPtr & rhs )
543 { return ! ( lhs == rhs ); }
544 /** \relates RWCOW_pointer */
545 template<class _D, class _Ptr>
546 inline bool operator!=( const typename _Ptr::_constPtr & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
547 { return ! ( lhs == rhs ); }
549 ///////////////////////////////////////////////////////////////////
552 /////////////////////////////////////////////////////////////////
554 ///////////////////////////////////////////////////////////////////
556 /** Forward declaration of Ptr types */
557 #define DEFINE_PTR_TYPE(NAME) \
559 extern void intrusive_ptr_add_ref( const NAME * ); \
560 extern void intrusive_ptr_release( const NAME * ); \
561 typedef zypp::intrusive_ptr<NAME> NAME##_Ptr; \
562 typedef zypp::intrusive_ptr<const NAME> NAME##_constPtr;
564 ///////////////////////////////////////////////////////////////////
565 #endif // ZYPP_BASE_PTRTYPES_H