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
19 #include <boost/scoped_ptr.hpp>
20 #include <boost/shared_ptr.hpp>
21 #include <boost/weak_ptr.hpp>
22 #include <boost/intrusive_ptr.hpp>
24 ///////////////////////////////////////////////////////////////////
26 { /////////////////////////////////////////////////////////////////
30 // printing void* (prevents us from including <ostream>)
31 std::string form( const char * format, ... ) __attribute__ ((format (printf, 1, 2)));
34 /** \defgroup ZYPP_SMART_PTR Smart pointer types
35 * Smart pointer types.
37 * Namespace zypp provides 3 smart pointer types \b using the
38 * boost smart pointer library.
40 * \li \c scoped_ptr Simple sole ownership of single objects. Noncopyable.
42 * \li \c shared_ptr Object ownership shared among multiple pointers
44 * \li \c weak_ptr Non-owning observers of an object owned by shared_ptr.
46 * And \ref zypp::RW_pointer, as wrapper around a smart pointer,
47 * poviding \c const correct read/write access to the object it refers.
51 /** shared_ptr custom deleter doing nothing.
52 * A custom deleter is a function being called when the
53 * last shared_ptr goes out of score. Per default the
54 * object gets deleted, but you can insall custom deleters
55 * as well. This one does nothing.
58 * // Some class providing a std::istream
61 * // Per deafult use std::cin.
63 * : _stream( &std::cin, NullDeleter() )
65 * // Or read from a file.
66 * InputStream( const Pathname & file_r )
67 * : _stream( new ifgzstream( _path.asString().c_str() ) )
69 * // Or use a stream priovided by the application.
70 * InputStream( std::istream & stream_r )
71 * : _stream( &stream_r, NullDeleter() )
74 * std::istream & stream()
75 * { return *_stream; }
78 * shared_ptr<std::istream> _stream;
84 void operator()( const void *const ) const
88 /** \class scoped_ptr */
89 using boost::scoped_ptr;
91 /** \class shared_ptr */
92 using boost::shared_ptr;
94 /** \class weak_ptr */
95 using boost::weak_ptr;
97 /** \class intrusive_ptr */
98 using boost::intrusive_ptr;
101 using boost::static_pointer_cast;
103 using boost::const_pointer_cast;
105 using boost::dynamic_pointer_cast;
107 /////////////////////////////////////////////////////////////////
109 ///////////////////////////////////////////////////////////////////
110 ///////////////////////////////////////////////////////////////////
112 { /////////////////////////////////////////////////////////////////
116 // typedef zypp::intrusive_ptr<Foo> Foo_Ptr; // see DEFINE_PTR_TYPE(NAME) macro below
119 // Defined in namespace std g++ finds the output operator (König-Lookup),
120 // even if we typedef the pointer in a different namespace than ::zypp.
121 // Otherwise we had to define an output operator always in the same namespace
122 // as the typedef (else g++ will just print the pointer value).
124 /** \relates zypp::shared_ptr Stream output. */
126 inline std::ostream & operator<<( std::ostream & str, const zypp::shared_ptr<D> & obj )
130 return str << std::string("NULL");
132 /** \overload specialize for void */
134 inline std::ostream & operator<<( std::ostream & str, const zypp::shared_ptr<void> & obj )
137 return str << zypp::str::form( "%p", (void*)obj.get() );
138 return str << std::string("NULL");
141 /** \relates zypp::shared_ptr Stream output. */
143 inline std::ostream & dumpOn( std::ostream & str, const zypp::shared_ptr<D> & obj )
146 return dumpOn( str, *obj );
147 return str << std::string("NULL");
149 /** \overload specialize for void */
151 inline std::ostream & dumpOn( std::ostream & str, const zypp::shared_ptr<void> & obj )
152 { return str << obj; }
154 /** \relates zypp::intrusive_ptr Stream output. */
156 inline std::ostream & operator<<( std::ostream & str, const zypp::intrusive_ptr<D> & obj )
160 return str << std::string("NULL");
162 /** \relates zypp::intrusive_ptr Stream output. */
164 inline std::ostream & dumpOn( std::ostream & str, const zypp::intrusive_ptr<D> & obj )
167 return dumpOn( str, *obj );
168 return str << std::string("NULL");
170 /////////////////////////////////////////////////////////////////
172 ///////////////////////////////////////////////////////////////////
173 ///////////////////////////////////////////////////////////////////
175 { /////////////////////////////////////////////////////////////////
177 ///////////////////////////////////////////////////////////////////
181 ///////////////////////////////////////////////////////////////////
183 * Don't forgett to provide versions for PtrType and constPtrType,
184 * esp. if creation a of temporary is not acceptable (eg. when
185 * checking the ref count value).
187 namespace rw_pointer {
192 typedef shared_ptr<D> PtrType;
193 typedef shared_ptr<const D> constPtrType;
194 /** Check whether pointer is not shared. */
195 bool unique( const constPtrType & ptr_r )
196 { return !ptr_r || ptr_r.unique(); }
197 bool unique( const PtrType & ptr_r )
198 { return !ptr_r || ptr_r.unique(); }
199 /** Return number of references. */
200 long use_count( const constPtrType & ptr_r ) const
201 { return ptr_r.use_count(); }
202 long use_count( const PtrType & ptr_r ) const
203 { return ptr_r.use_count(); }
209 typedef intrusive_ptr<D> PtrType;
210 typedef intrusive_ptr<const D> constPtrType;
211 /** Check whether pointer is not shared. */
212 bool unique( const constPtrType & ptr_r )
213 { return !ptr_r || (ptr_r->refCount() <= 1); }
214 bool unique( const PtrType & ptr_r )
215 { return !ptr_r || (ptr_r->refCount() <= 1); }
216 /** Return number of references. */
217 long use_count( const constPtrType & ptr_r ) const
218 { return ptr_r ? ptr_r->refCount() : 0; }
219 long use_count( const PtrType & ptr_r ) const
220 { return ptr_r ? ptr_r->refCount() : 0; }
226 typedef scoped_ptr<D> PtrType;
227 typedef scoped_ptr<const D> constPtrType;
228 /** Check whether pointer is not shared. */
229 bool unique( const constPtrType & ptr_r )
231 bool unique( const PtrType & ptr_r )
233 /** Return number of references. */
234 long use_count( const constPtrType & ptr_r ) const
235 { return ptr_r ? 1 : 0; }
236 long use_count( const PtrType & ptr_r ) const
237 { return ptr_r ? 1 : 0; }
241 ///////////////////////////////////////////////////////////////////
243 ///////////////////////////////////////////////////////////////////
245 // CLASS NAME : RW_pointer
247 /** Wrapper for \c const correct access via \ref ZYPP_SMART_PTR.
249 * zypp::RW_pointer<tt>\<D,DTraits></tt> stores a \ref ZYPP_SMART_PTR
250 * of type \c DTraits::PtrType, which must be convertible into a <tt>D *</tt>.
251 * Pointer style access (via \c -> and \c *) offers a <tt>const D *</tt> in const
252 * a context, otherwise a <tt>D *</tt>. Thus \em RW_ means \em read/write,
253 * as you get a different type, dependent on whether you're allowed to
256 * Forwarding access from an interface to an implemantation class, an
257 * RW_pointer prevents const interface methods from accidentally calling
258 * nonconst implementation methods.
260 * The second template argument defaults to
261 * <tt>DTraits = rw_pointer::Shared<D></tt> thus wraping a
262 * <tt>shared_ptr<D></tt>. To wrap an <tt>intrusive_ptr<D></tt>
263 * use <tt>rw_pointer::Intrusive<D></tt>.
265 * \see zypp::RWCOW_pointer for 'copy on write' functionality.
268 * #include "zypp/base/PtrTypes.h"
274 * // Implementation class
276 * // Pointer to implementation; actually a shared_ptr<Impl>
277 * RW_pointer<Impl> _pimpl;
279 * void baa() { _pimpl->... } // is Impl *
280 * void baa() const { _pimpl->... } // is Impl const *
284 template<class D, class DTraits = rw_pointer::Shared<D> >
287 typedef typename DTraits::PtrType PtrType;
288 typedef typename DTraits::constPtrType constPtrType;
293 RW_pointer( std::nullptr_t )
297 RW_pointer( typename PtrType::element_type * dptr )
302 RW_pointer( PtrType dptr )
306 RW_pointer & operator=( std::nullptr_t )
307 { reset(); return *this; }
310 { PtrType().swap( _dptr ); }
312 void reset( typename PtrType::element_type * dptr )
313 { PtrType( dptr ).swap( _dptr ); }
315 void swap( RW_pointer & rhs )
316 { _dptr.swap( rhs._dptr ); }
318 void swap( PtrType & rhs )
319 { _dptr.swap( rhs ); }
321 explicit operator bool() const
322 { return _dptr.get() != nullptr; }
324 const D & operator*() const
327 const D * operator->() const
328 { return _dptr.operator->(); }
330 const D * get() const
331 { return _dptr.get(); }
337 { return _dptr.operator->(); }
340 { return _dptr.get(); }
344 { return DTraits().unique( _dptr ); }
346 long use_count() const
347 { return DTraits().use_count( _dptr ); }
349 constPtrType getPtr() const
355 constPtrType cgetPtr()
361 ///////////////////////////////////////////////////////////////////
363 /** \relates RW_pointer Stream output.
365 * Print the \c D object the RW_pointer refers, or \c "NULL"
366 * if the pointer is \c NULL.
368 template<class D, class DPtr>
369 inline std::ostream & operator<<( std::ostream & str, const RW_pointer<D, DPtr> & obj )
372 return str << *obj.get();
373 return str << std::string("NULL");
376 /** \relates RW_pointer */
377 template<class D, class DPtr>
378 inline bool operator==( const RW_pointer<D, DPtr> & lhs, const RW_pointer<D, DPtr> & rhs )
379 { return( lhs.get() == rhs.get() ); }
380 /** \relates RW_pointer */
381 template<class D, class DPtr>
382 inline bool operator==( const RW_pointer<D, DPtr> & lhs, const typename DPtr::PtrType & rhs )
383 { return( lhs.get() == rhs.get() ); }
384 /** \relates RW_pointer */
385 template<class D, class DPtr>
386 inline bool operator==( const typename DPtr::PtrType & lhs, const RW_pointer<D, DPtr> & rhs )
387 { return( lhs.get() == rhs.get() ); }
388 /** \relates RW_pointer */
389 template<class D, class DPtr>
390 inline bool operator==( const RW_pointer<D, DPtr> & lhs, const typename DPtr::constPtrType & rhs )
391 { return( lhs.get() == rhs.get() ); }
392 /** \relates RW_pointer */
393 template<class D, class DPtr>
394 inline bool operator==( const typename DPtr::constPtrType & lhs, const RW_pointer<D, DPtr> & rhs )
395 { return( lhs.get() == rhs.get() ); }
396 /** \relates RW_pointer */
397 template<class D, class DPtr>
398 inline bool operator==( const RW_pointer<D, DPtr> & lhs, std::nullptr_t )
399 { return( lhs.get() == nullptr ); }
400 /** \relates RW_pointer */
401 template<class D, class DPtr>
402 inline bool operator==( std::nullptr_t, const RW_pointer<D, DPtr> & rhs )
403 { return( nullptr == rhs.get() ); }
406 /** \relates RW_pointer */
407 template<class D, class DPtr>
408 inline bool operator!=( const RW_pointer<D, DPtr> & lhs, const RW_pointer<D, DPtr> & rhs )
409 { return ! ( lhs == rhs ); }
410 /** \relates RW_pointer */
411 template<class D, class DPtr>
412 inline bool operator!=( const RW_pointer<D, DPtr> & lhs, const typename DPtr::PtrType & rhs )
413 { return ! ( lhs == rhs ); }
414 /** \relates RW_pointer */
415 template<class D, class DPtr>
416 inline bool operator!=( const typename DPtr::PtrType & lhs, const RW_pointer<D, DPtr> & rhs )
417 { return ! ( lhs == rhs ); }
418 /** \relates RW_pointer */
419 template<class D, class DPtr>
420 inline bool operator!=( const RW_pointer<D, DPtr> & lhs, const typename DPtr::constPtrType & rhs )
421 { return ! ( lhs == rhs ); }
422 /** \relates RW_pointer */
423 template<class D, class DPtr>
424 inline bool operator!=( const typename DPtr::constPtrType & lhs, const RW_pointer<D, DPtr> & rhs )
425 { return ! ( lhs == rhs ); }
426 /** \relates RW_pointer */
427 template<class D, class DPtr>
428 inline bool operator!=( const RW_pointer<D, DPtr> & lhs, std::nullptr_t )
429 { return( lhs.get() != nullptr ); }
430 /** \relates RW_pointer */
431 template<class D, class DPtr>
432 inline bool operator!=( std::nullptr_t, const RW_pointer<D, DPtr> & rhs )
433 { return( nullptr != rhs.get() ); }
435 ///////////////////////////////////////////////////////////////////
437 /** \relates RWCOW_pointer Clone the underlying object.
438 * Calls \a rhs <tt>-\>clone()</tt>. Being defined as a
439 * function outside \ref RWCOW_pointer allows to overload
440 * it, in case a specific \a D does not have <tt>clone()</tt>.
443 inline D * rwcowClone( const D * rhs )
444 { return rhs->clone(); }
446 ///////////////////////////////////////////////////////////////////
448 // CLASS NAME : RWCOW_pointer
450 /** \ref RW_pointer supporting 'copy on write' functionality.
452 * \em Write access to the underlying object creates a copy, iff
453 * the object is shared.
455 * See \ref RW_pointer.
457 template<class D, class DTraits = rw_pointer::Shared<D> >
460 typedef typename DTraits::PtrType PtrType;
461 typedef typename DTraits::constPtrType constPtrType;
466 RWCOW_pointer( std::nullptr_t )
470 RWCOW_pointer( typename PtrType::element_type * dptr )
475 RWCOW_pointer( PtrType dptr )
479 RWCOW_pointer & operator=( std::nullptr_t )
480 { reset(); return *this; }
483 { PtrType().swap( _dptr ); }
485 void reset( typename PtrType::element_type * dptr )
486 { PtrType( dptr ).swap( _dptr ); }
488 void swap( RWCOW_pointer & rhs )
489 { _dptr.swap( rhs._dptr ); }
491 void swap( PtrType & rhs )
492 { _dptr.swap( rhs ); }
494 explicit operator bool() const
495 { return _dptr.get() != nullptr; }
497 const D & operator*() const
500 const D * operator->() const
501 { return _dptr.operator->(); }
503 const D * get() const
504 { return _dptr.get(); }
507 { assertUnshared(); return *_dptr; }
510 { assertUnshared(); return _dptr.operator->(); }
513 { assertUnshared(); return _dptr.get(); }
517 { return DTraits().unique( _dptr ); }
519 long use_count() const
520 { return DTraits().use_count( _dptr ); }
522 constPtrType getPtr() const
526 { assertUnshared(); return _dptr; }
528 constPtrType cgetPtr()
533 void assertUnshared()
536 PtrType( rwcowClone( _dptr.get() ) ).swap( _dptr );
542 ///////////////////////////////////////////////////////////////////
544 /** \relates RWCOW_pointer Stream output.
546 * Print the \c D object the RWCOW_pointer refers, or \c "NULL"
547 * if the pointer is \c NULL.
549 template<class D, class DPtr>
550 inline std::ostream & operator<<( std::ostream & str, const RWCOW_pointer<D, DPtr> & obj )
553 return str << *obj.get();
554 return str << std::string("NULL");
557 /** \relates RWCOW_pointer */
558 template<class D, class DPtr>
559 inline bool operator==( const RWCOW_pointer<D, DPtr> & lhs, const RWCOW_pointer<D, DPtr> & rhs )
560 { return( lhs.get() == rhs.get() ); }
561 /** \relates RWCOW_pointer */
562 template<class D, class DPtr>
563 inline bool operator==( const RWCOW_pointer<D, DPtr> & lhs, const typename DPtr::PtrType & rhs )
564 { return( lhs.get() == rhs.get() ); }
565 /** \relates RWCOW_pointer */
566 template<class D, class DPtr>
567 inline bool operator==( const typename DPtr::PtrType & lhs, const RWCOW_pointer<D, DPtr> & rhs )
568 { return( lhs.get() == rhs.get() ); }
569 /** \relates RWCOW_pointer */
570 template<class D, class DPtr>
571 inline bool operator==( const RWCOW_pointer<D, DPtr> & lhs, const typename DPtr::constPtrType & rhs )
572 { return( lhs.get() == rhs.get() ); }
573 /** \relates RWCOW_pointer */
574 template<class D, class DPtr>
575 inline bool operator==( const typename DPtr::constPtrType & lhs, const RWCOW_pointer<D, DPtr> & rhs )
576 { return( lhs.get() == rhs.get() ); }
577 /** \relates RWCOW_pointer */
578 template<class D, class DPtr>
579 inline bool operator==( const RWCOW_pointer<D, DPtr> & lhs, std::nullptr_t )
580 { return( lhs.get() == nullptr ); }
581 /** \relates RWCOW_pointer */
582 template<class D, class DPtr>
583 inline bool operator==( std::nullptr_t, const RWCOW_pointer<D, DPtr> & rhs )
584 { return( nullptr == rhs.get() ); }
586 /** \relates RWCOW_pointer */
587 template<class D, class DPtr>
588 inline bool operator!=( const RWCOW_pointer<D, DPtr> & lhs, const RWCOW_pointer<D, DPtr> & rhs )
589 { return ! ( lhs == rhs ); }
590 /** \relates RWCOW_pointer */
591 template<class D, class DPtr>
592 inline bool operator!=( const RWCOW_pointer<D, DPtr> & lhs, const typename DPtr::PtrType & rhs )
593 { return ! ( lhs == rhs ); }
594 /** \relates RWCOW_pointer */
595 template<class D, class DPtr>
596 inline bool operator!=( const typename DPtr::PtrType & lhs, const RWCOW_pointer<D, DPtr> & rhs )
597 { return ! ( lhs == rhs ); }
598 /** \relates RWCOW_pointer */
599 template<class D, class DPtr>
600 inline bool operator!=( const RWCOW_pointer<D, DPtr> & lhs, const typename DPtr::constPtrType & rhs )
601 { return ! ( lhs == rhs ); }
602 /** \relates RWCOW_pointer */
603 template<class D, class DPtr>
604 inline bool operator!=( const typename DPtr::constPtrType & lhs, const RWCOW_pointer<D, DPtr> & rhs )
605 { return ! ( lhs == rhs ); }
606 /** \relates RWCOW_pointer */
607 template<class D, class DPtr>
608 inline bool operator!=( const RWCOW_pointer<D, DPtr> & lhs, std::nullptr_t )
609 { return( lhs.get() != nullptr ); }
610 /** \relates RWCOW_pointer */
611 template<class D, class DPtr>
612 inline bool operator!=( std::nullptr_t, const RWCOW_pointer<D, DPtr> & rhs )
613 { return( nullptr != rhs.get() ); }
615 ///////////////////////////////////////////////////////////////////
618 /////////////////////////////////////////////////////////////////
620 ///////////////////////////////////////////////////////////////////
622 /** Forward declaration of Ptr types */
623 #define DEFINE_PTR_TYPE(NAME) \
625 extern void intrusive_ptr_add_ref( const NAME * ); \
626 extern void intrusive_ptr_release( const NAME * ); \
627 typedef zypp::intrusive_ptr<NAME> NAME##_Ptr; \
628 typedef zypp::intrusive_ptr<const NAME> NAME##_constPtr;
630 ///////////////////////////////////////////////////////////////////
631 #endif // ZYPP_BASE_PTRTYPES_H