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;
273 RW_pointer( std::nullptr_t )
277 RW_pointer( typename _Ptr::element_type * dptr )
282 RW_pointer( _Ptr dptr )
286 RW_pointer & operator=( std::nullptr_t )
287 { reset(); return *this; }
290 { _Ptr().swap( _dptr ); }
292 void reset( typename _Ptr::element_type * dptr )
293 { _Ptr( dptr ).swap( _dptr ); }
295 void swap( RW_pointer & rhs )
296 { _dptr.swap( rhs._dptr ); }
298 void swap( _Ptr & rhs )
299 { _dptr.swap( rhs ); }
301 explicit operator bool() const
302 { return _dptr.get() != nullptr; }
304 const _D & operator*() const
307 const _D * operator->() const
308 { return _dptr.operator->(); }
310 const _D * get() const
311 { return _dptr.get(); }
317 { return _dptr.operator->(); }
320 { return _dptr.get(); }
324 { return _Traits().unique( _dptr ); }
326 long use_count() const
327 { return _Traits().use_count( _dptr ); }
329 _constPtr getPtr() const
341 ///////////////////////////////////////////////////////////////////
343 /** \relates RW_pointer Stream output.
345 * Print the \c _D object the RW_pointer refers, or \c "NULL"
346 * if the pointer is \c NULL.
348 template<class _D, class _Ptr>
349 inline std::ostream & operator<<( std::ostream & str, const RW_pointer<_D, _Ptr> & obj )
352 return str << *obj.get();
353 return str << std::string("NULL");
356 /** \relates RW_pointer */
357 template<class _D, class _Ptr>
358 inline bool operator==( const RW_pointer<_D, _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::_Ptr & rhs )
363 { return( lhs.get() == rhs.get() ); }
364 /** \relates RW_pointer */
365 template<class _D, class _Ptr>
366 inline bool operator==( const typename _Ptr::_Ptr & lhs, const RW_pointer<_D, _Ptr> & rhs )
367 { return( lhs.get() == rhs.get() ); }
368 /** \relates RW_pointer */
369 template<class _D, class _Ptr>
370 inline bool operator==( const RW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_constPtr & rhs )
371 { return( lhs.get() == rhs.get() ); }
372 /** \relates RW_pointer */
373 template<class _D, class _Ptr>
374 inline bool operator==( const typename _Ptr::_constPtr & lhs, const RW_pointer<_D, _Ptr> & rhs )
375 { return( lhs.get() == rhs.get() ); }
376 /** \relates RW_pointer */
377 template<class _D, class _Ptr>
378 inline bool operator==( const RW_pointer<_D, _Ptr> & lhs, std::nullptr_t )
379 { return( lhs.get() == nullptr ); }
380 /** \relates RW_pointer */
381 template<class _D, class _Ptr>
382 inline bool operator==( std::nullptr_t, const RW_pointer<_D, _Ptr> & rhs )
383 { return( nullptr == rhs.get() ); }
386 /** \relates RW_pointer */
387 template<class _D, class _Ptr>
388 inline bool operator!=( const RW_pointer<_D, _Ptr> & lhs, const RW_pointer<_D, _Ptr> & rhs )
389 { return ! ( lhs == rhs ); }
390 /** \relates RW_pointer */
391 template<class _D, class _Ptr>
392 inline bool operator!=( const RW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_Ptr & rhs )
393 { return ! ( lhs == rhs ); }
394 /** \relates RW_pointer */
395 template<class _D, class _Ptr>
396 inline bool operator!=( const typename _Ptr::_Ptr & lhs, const RW_pointer<_D, _Ptr> & rhs )
397 { return ! ( lhs == rhs ); }
398 /** \relates RW_pointer */
399 template<class _D, class _Ptr>
400 inline bool operator!=( const RW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_constPtr & rhs )
401 { return ! ( lhs == rhs ); }
402 /** \relates RW_pointer */
403 template<class _D, class _Ptr>
404 inline bool operator!=( const typename _Ptr::_constPtr & lhs, const RW_pointer<_D, _Ptr> & rhs )
405 { return ! ( lhs == rhs ); }
406 /** \relates RW_pointer */
407 template<class _D, class _Ptr>
408 inline bool operator!=( const RW_pointer<_D, _Ptr> & lhs, std::nullptr_t )
409 { return( lhs.get() != nullptr ); }
410 /** \relates RW_pointer */
411 template<class _D, class _Ptr>
412 inline bool operator!=( std::nullptr_t, const RW_pointer<_D, _Ptr> & rhs )
413 { return( nullptr != rhs.get() ); }
415 ///////////////////////////////////////////////////////////////////
417 /** \relates RWCOW_pointer Clone the underlying object.
418 * Calls \a rhs <tt>-\>clone()</tt>. Being defined as a
419 * function outside \ref RWCOW_pointer allows to overload
420 * it, in case a specific \a _D does not have <tt>clone()</tt>.
423 inline _D * rwcowClone( const _D * rhs )
424 { return rhs->clone(); }
426 ///////////////////////////////////////////////////////////////////
428 // CLASS NAME : RWCOW_pointer
430 /** \ref RW_pointer supporting 'copy on write' functionality.
432 * \em Write access to the underlying object creates a copy, iff
433 * the object is shared.
435 * See \ref RW_pointer.
437 template<class _D, class _Traits = rw_pointer::Shared<_D> >
440 typedef typename _Traits::_Ptr _Ptr;
441 typedef typename _Traits::_constPtr _constPtr;
446 RWCOW_pointer( std::nullptr_t )
450 RWCOW_pointer( typename _Ptr::element_type * dptr )
455 RWCOW_pointer( _Ptr dptr )
459 RWCOW_pointer & operator=( std::nullptr_t )
460 { reset(); return *this; }
463 { _Ptr().swap( _dptr ); }
465 void reset( typename _Ptr::element_type * dptr )
466 { _Ptr( dptr ).swap( _dptr ); }
468 void swap( RWCOW_pointer & rhs )
469 { _dptr.swap( rhs._dptr ); }
471 void swap( _Ptr & rhs )
472 { _dptr.swap( rhs ); }
474 explicit operator bool() const
475 { return _dptr.get() != nullptr; }
477 const _D & operator*() const
480 const _D * operator->() const
481 { return _dptr.operator->(); }
483 const _D * get() const
484 { return _dptr.get(); }
487 { assertUnshared(); return *_dptr; }
490 { assertUnshared(); return _dptr.operator->(); }
493 { assertUnshared(); return _dptr.get(); }
497 { return _Traits().unique( _dptr ); }
499 long use_count() const
500 { return _Traits().use_count( _dptr ); }
502 _constPtr getPtr() const
506 { assertUnshared(); return _dptr; }
513 void assertUnshared()
516 _Ptr( rwcowClone( _dptr.get() ) ).swap( _dptr );
522 ///////////////////////////////////////////////////////////////////
524 /** \relates RWCOW_pointer Stream output.
526 * Print the \c _D object the RWCOW_pointer refers, or \c "NULL"
527 * if the pointer is \c NULL.
529 template<class _D, class _Ptr>
530 inline std::ostream & operator<<( std::ostream & str, const RWCOW_pointer<_D, _Ptr> & obj )
533 return str << *obj.get();
534 return str << std::string("NULL");
537 /** \relates RWCOW_pointer */
538 template<class _D, class _Ptr>
539 inline bool operator==( const RWCOW_pointer<_D, _Ptr> & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
540 { return( lhs.get() == rhs.get() ); }
541 /** \relates RWCOW_pointer */
542 template<class _D, class _Ptr>
543 inline bool operator==( const RWCOW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_Ptr & rhs )
544 { return( lhs.get() == rhs.get() ); }
545 /** \relates RWCOW_pointer */
546 template<class _D, class _Ptr>
547 inline bool operator==( const typename _Ptr::_Ptr & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
548 { return( lhs.get() == rhs.get() ); }
549 /** \relates RWCOW_pointer */
550 template<class _D, class _Ptr>
551 inline bool operator==( const RWCOW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_constPtr & rhs )
552 { return( lhs.get() == rhs.get() ); }
553 /** \relates RWCOW_pointer */
554 template<class _D, class _Ptr>
555 inline bool operator==( const typename _Ptr::_constPtr & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
556 { return( lhs.get() == rhs.get() ); }
557 /** \relates RWCOW_pointer */
558 template<class _D, class _Ptr>
559 inline bool operator==( const RWCOW_pointer<_D, _Ptr> & lhs, std::nullptr_t )
560 { return( lhs.get() == nullptr ); }
561 /** \relates RWCOW_pointer */
562 template<class _D, class _Ptr>
563 inline bool operator==( std::nullptr_t, const RWCOW_pointer<_D, _Ptr> & rhs )
564 { return( nullptr == rhs.get() ); }
566 /** \relates RWCOW_pointer */
567 template<class _D, class _Ptr>
568 inline bool operator!=( const RWCOW_pointer<_D, _Ptr> & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
569 { return ! ( lhs == rhs ); }
570 /** \relates RWCOW_pointer */
571 template<class _D, class _Ptr>
572 inline bool operator!=( const RWCOW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_Ptr & rhs )
573 { return ! ( lhs == rhs ); }
574 /** \relates RWCOW_pointer */
575 template<class _D, class _Ptr>
576 inline bool operator!=( const typename _Ptr::_Ptr & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
577 { return ! ( lhs == rhs ); }
578 /** \relates RWCOW_pointer */
579 template<class _D, class _Ptr>
580 inline bool operator!=( const RWCOW_pointer<_D, _Ptr> & lhs, const typename _Ptr::_constPtr & rhs )
581 { return ! ( lhs == rhs ); }
582 /** \relates RWCOW_pointer */
583 template<class _D, class _Ptr>
584 inline bool operator!=( const typename _Ptr::_constPtr & lhs, const RWCOW_pointer<_D, _Ptr> & rhs )
585 { return ! ( lhs == rhs ); }
586 /** \relates RWCOW_pointer */
587 template<class _D, class _Ptr>
588 inline bool operator!=( const RWCOW_pointer<_D, _Ptr> & lhs, std::nullptr_t )
589 { return( lhs.get() != nullptr ); }
590 /** \relates RWCOW_pointer */
591 template<class _D, class _Ptr>
592 inline bool operator!=( std::nullptr_t, const RWCOW_pointer<_D, _Ptr> & rhs )
593 { return( nullptr != rhs.get() ); }
595 ///////////////////////////////////////////////////////////////////
598 /////////////////////////////////////////////////////////////////
600 ///////////////////////////////////////////////////////////////////
602 /** Forward declaration of Ptr types */
603 #define DEFINE_PTR_TYPE(NAME) \
605 extern void intrusive_ptr_add_ref( const NAME * ); \
606 extern void intrusive_ptr_release( const NAME * ); \
607 typedef zypp::intrusive_ptr<NAME> NAME##_Ptr; \
608 typedef zypp::intrusive_ptr<const NAME> NAME##_constPtr;
610 ///////////////////////////////////////////////////////////////////
611 #endif // ZYPP_BASE_PTRTYPES_H