doxygen fixes
[platform/upstream/libzypp.git] / zypp / base / PtrTypes.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/base/PtrTypes.h
10  *  \ingroup ZYPP_SMART_PTR
11  *  \see ZYPP_SMART_PTR
12 */
13 #ifndef ZYPP_BASE_PTRTYPES_H
14 #define ZYPP_BASE_PTRTYPES_H
15
16 #include <string>
17
18 #include <boost/scoped_ptr.hpp>
19 #include <boost/shared_ptr.hpp>
20 #include <boost/weak_ptr.hpp>
21 #include <boost/intrusive_ptr.hpp>
22
23 ///////////////////////////////////////////////////////////////////
24 namespace zypp
25 { /////////////////////////////////////////////////////////////////
26
27     /** \defgroup ZYPP_SMART_PTR Smart pointer types
28      *  Smart pointer types.
29      *
30      * Namespace zypp provides 3 smart pointer types \b using the
31      * boost smart pointer library.
32      *
33      * \li \c scoped_ptr Simple sole ownership of single objects. Noncopyable.
34      *
35      * \li \c shared_ptr Object ownership shared among multiple pointers
36      *
37      * \li \c weak_ptr Non-owning observers of an object owned by shared_ptr.
38      *
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.
41     */
42     /*@{*/
43
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.
49      *
50      * \code
51      *  // Some class providing a std::istream
52      *  struct InpuStream
53      * {
54      *   // Per deafult use std::cin.
55      *   InputStream()
56      *   : _stream( &std::cin, NullDeleter() )
57      *   {}
58      *   // Or read from a file.
59      *   InputStream( const Pathname & file_r )
60      *   : _stream( new ifgzstream( _path.asString().c_str() ) )
61      *   {}
62      *   // Or use a stream priovided by the application.
63      *   InputStream( std::istream & stream_r )
64      *   : _stream( &stream_r, NullDeleter() )
65      *   {}
66      *
67      *   std::istream & stream()
68      *   { return *_stream; }
69      *
70      * private:
71      *   shared_ptr<std::istream> _stream;
72      * };
73      * \endcode
74     */
75     struct NullDeleter
76     {
77       void operator()( const void *const ) const
78       {}
79     };
80
81     /** \class scoped_ptr */
82     using boost::scoped_ptr;
83
84     /** \class shared_ptr */
85     using boost::shared_ptr;
86
87     /** \class weak_ptr */
88     using boost::weak_ptr;
89
90     /** \class intrusive_ptr */
91     using boost::intrusive_ptr;
92
93     /** */
94     using boost::static_pointer_cast;
95     /**  */
96     using boost::const_pointer_cast;
97     /**  */
98     using boost::dynamic_pointer_cast;
99
100     /** \relates shared_ptr Stream output. */
101     template<class _D>
102       inline std::ostream &
103       operator<<( std::ostream & str, const shared_ptr<_D> & obj )
104       {
105         if ( obj )
106           return str << *obj;
107         return str << std::string("NULL");
108       }
109
110     /** \relates intrusive_ptr Stream output. */
111     template<class _D>
112       inline std::ostream &
113       operator<<( std::ostream & str, const intrusive_ptr<_D> & obj )
114       {
115         if ( obj )
116           return str << *obj;
117         return str << std::string("NULL");
118       }
119
120     ///////////////////////////////////////////////////////////////////
121     //
122     //  RW_pointer traits
123     //
124     ///////////////////////////////////////////////////////////////////
125     /**
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).
129     */
130     namespace rw_pointer {
131
132       template<class _D>
133         struct Shared
134         {
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(); }
147         };
148
149       template<class _D>
150         struct Intrusive
151         {
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; }
164         };
165     }
166     ///////////////////////////////////////////////////////////////////
167
168     ///////////////////////////////////////////////////////////////////
169     //
170     //  CLASS NAME : RW_pointer
171     //
172     /** Wrapper for \c const correct access via \ref ZYPP_SMART_PTR.
173      *
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
179      * read or write.
180      *
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.
184      *
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>.
189      *
190      * \see zypp::RWCOW_pointer for 'copy on write' functionality.
191      *
192      * \code
193      * #include "zypp/base/PtrTypes.h"
194      *
195      * class Foo
196      * {
197      *   ...
198      *   private:
199      *     // Implementation class
200      *     struct Impl;
201      *     // Pointer to implementation; actually a shared_ptr<Impl>
202      *     RW_pointer<Impl> _pimpl;
203      *
204      *     void baa()       { _pimpl->... } // is Impl *
205      *     void baa() const { _pimpl->... } // is Impl const *
206      * };
207      * \endcode
208     */
209     template<class _D, class _Traits = rw_pointer::Shared<_D> >
210       struct RW_pointer
211       {
212         typedef typename _Traits::_Ptr               _Ptr;
213         typedef typename _Traits::_constPtr          _constPtr;
214         typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
215
216         explicit
217         RW_pointer( typename _Ptr::element_type * dptr = 0 )
218         : _dptr( dptr )
219         {}
220
221         explicit
222         RW_pointer( _Ptr dptr )
223         : _dptr( dptr )
224         {}
225
226         void reset()
227         { _Ptr().swap( _dptr ); }
228
229         void reset( typename _Ptr::element_type * dptr )
230         { _Ptr( dptr ).swap( _dptr ); }
231
232         void swap( RW_pointer & rhs )
233         { _dptr.swap( rhs._dptr ); }
234
235         void swap( _Ptr & rhs )
236         { _dptr.swap( rhs ); }
237
238         operator unspecified_bool_type() const
239         { return _dptr; }
240
241         const _D & operator*() const
242         { return *_dptr; };
243
244         const _D * operator->() const
245         { return _dptr.get(); }
246
247         const _D * get() const
248         { return _dptr.get(); }
249
250         _D & operator*()
251         { return *_dptr; }
252
253         _D * operator->()
254         { return _dptr.get(); }
255
256         _D * get()
257         { return _dptr.get(); }
258
259       public:
260         bool unique() const
261         { return _Traits().unique( _dptr ); }
262
263         long use_count() const
264         { return _Traits().use_count( _dptr ); }
265
266         _constPtr getPtr() const
267         { return _dptr; }
268
269         _Ptr getPtr()
270         { return _dptr; }
271
272       private:
273         _Ptr _dptr;
274       };
275     ///////////////////////////////////////////////////////////////////
276
277     /** \relates RW_pointer Stream output.
278      *
279      * Print the \c _D object the RW_pointer refers, or \c "NULL"
280      * if the pointer is \c NULL.
281     */
282     template<class _D, class _Ptr>
283       inline std::ostream &
284       operator<<( std::ostream & str, const RW_pointer<_D, _Ptr> & obj )
285       {
286         if ( obj.get() )
287           return str << *obj.get();
288         return str << std::string("NULL");
289       }
290
291     ///////////////////////////////////////////////////////////////////
292
293     ///////////////////////////////////////////////////////////////////
294     //
295     //  CLASS NAME : RWCOW_pointer
296     //
297     /** \ref RW_pointer supporting 'copy on write' functionality.
298      *
299      * \em Write access to the underlying object creates a copy, iff
300      * the object is shared.
301      *
302      * See \ref RW_pointer.
303     */
304     template<class _D, class _Traits = rw_pointer::Shared<_D> >
305       struct RWCOW_pointer
306       {
307         typedef typename _Traits::_Ptr               _Ptr;
308         typedef typename _Traits::_constPtr          _constPtr;
309         typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
310
311         explicit
312         RWCOW_pointer( typename _Ptr::element_type * dptr = 0 )
313         : _dptr( dptr )
314         {}
315
316         explicit
317         RWCOW_pointer( _Ptr dptr )
318         : _dptr( dptr )
319         {}
320
321         void reset()
322         { _Ptr().swap( _dptr ); }
323
324         void reset( typename _Ptr::element_type * dptr )
325         { _Ptr( dptr ).swap( _dptr ); }
326
327         void swap( RWCOW_pointer & rhs )
328         { _dptr.swap( rhs._dptr ); }
329
330         void swap( _Ptr & rhs )
331         { _dptr.swap( rhs ); }
332
333         operator unspecified_bool_type() const
334         { return _dptr; }
335
336         const _D & operator*() const
337         { return *_dptr; };
338
339         const _D * operator->() const
340         { return _dptr.get(); }
341
342         const _D * get() const
343         { return _dptr.get(); }
344
345         _D & operator*()
346         { assertUnshared(); return *_dptr; }
347
348         _D * operator->()
349         { assertUnshared(); return _dptr.get(); }
350
351         _D * get()
352         { assertUnshared(); return _dptr.get(); }
353
354       public:
355         bool unique() const
356         { return _Traits().unique( _dptr ); }
357
358         long use_count() const
359         { return _Traits().use_count( _dptr ); }
360
361         _constPtr getPtr() const
362         { return _dptr; }
363
364         _Ptr getPtr()
365         { assertUnshared(); return _dptr; }
366
367       private:
368
369         void assertUnshared()
370         {
371           if ( !unique() )
372             _Ptr( rwcowClone( _dptr.get() ) ).swap( _dptr );
373         }
374
375       private:
376         _Ptr _dptr;
377       };
378     ///////////////////////////////////////////////////////////////////
379
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>.
384     */
385     template<class _D>
386       inline _D * rwcowClone( const _D * rhs )
387       { return rhs->clone(); }
388
389     ///////////////////////////////////////////////////////////////////
390
391     /** \relates RWCOW_pointer Stream output.
392      *
393      * Print the \c _D object the RWCOW_pointer refers, or \c "NULL"
394      * if the pointer is \c NULL.
395     */
396     template<class _D, class _Ptr>
397       inline std::ostream &
398       operator<<( std::ostream & str, const RWCOW_pointer<_D, _Ptr> & obj )
399       {
400         if ( obj.get() )
401           return str << *obj.get();
402         return str << std::string("NULL");
403       }
404
405     ///////////////////////////////////////////////////////////////////
406
407     /*@}*/
408
409   /////////////////////////////////////////////////////////////////
410 } // namespace zypp
411 ///////////////////////////////////////////////////////////////////
412
413 /** Forward declaration of Ptr types */
414 #define DEFINE_PTR_TYPE(NAME) \
415 class 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;
420
421 ///////////////////////////////////////////////////////////////////
422 #endif // ZYPP_BASE_PTRTYPES_H