- Added support to share a CD mount
[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     /** \class scoped_ptr scoped_ptr */
45     using boost::scoped_ptr;
46
47     /** \class shared_ptr */
48     using boost::shared_ptr;
49
50     /** \class weak_ptr */
51     using boost::weak_ptr;
52
53     /** \class intrusive_ptr */
54     using boost::intrusive_ptr;
55
56     /**  */
57     using boost::static_pointer_cast;
58     /**  */
59     using boost::const_pointer_cast;
60     /**  */
61     using boost::dynamic_pointer_cast;
62
63     ///////////////////////////////////////////////////////////////////
64     //
65     //  RW_pointer traits
66     //
67     ///////////////////////////////////////////////////////////////////
68     namespace rw_pointer {
69
70       template<class _D>
71         struct Shared
72         {
73           typedef shared_ptr<_D>       _Ptr;
74           typedef shared_ptr<const _D> _constPtr;
75           /** Check whether pointer is shared. */
76           bool isShared( const _constPtr & ptr_r )
77           { return ptr_r.use_count() > 1; }
78         };
79
80       template<class _D>
81         struct Intrusive
82         {
83           typedef intrusive_ptr<_D>       _Ptr;
84           typedef intrusive_ptr<const _D> _constPtr;
85           /** Check whether pointer is shared. */
86           bool isShared( const _constPtr & ptr_r )
87           { return ptr_r && (ptr_r->refCount() > 1); }
88         };
89     }
90     ///////////////////////////////////////////////////////////////////
91
92     ///////////////////////////////////////////////////////////////////
93     //
94     //  CLASS NAME : RW_pointer
95     //
96     /** Wrapper for \c const correct access via \ref ZYPP_SMART_PTR.
97      *
98      * zypp::RW_pointer<tt>\<_D,_Traits></tt> stores a \ref ZYPP_SMART_PTR
99      * of type \c _Traits::_Ptr, which must be convertible into a <tt>_D *</tt>.
100      * Pointer style access (via \c -> and \c *) offers a <tt>const _D *</tt> in const
101      * a context, otherwise a <tt>_D *</tt>. Thus \em RW_ means \em read/write,
102      * as you get a different type, dependent on whether you're allowed to
103      * read or write.
104      *
105      * Forwarding access from an interface to an implemantation class, an
106      * RW_pointer prevents const interface methods from accidentally calling
107      * nonconst implementation methods.
108      *
109      * The second template argument defaults to
110      * <tt>_Traits = rw_pointer::Shared<_D></tt> thus wraping a
111      * <tt>shared_ptr<_D></tt>. To wrap an <tt>intrusive_ptr<_D></tt>
112      * use <tt>rw_pointer::Intrusive<_D></tt>.
113      *
114      * \see zypp::RWCOW_pointer for 'copy on write' functionality.
115      *
116      * \code
117      * #include "zypp/base/PtrTypes.h"
118      *
119      * class Foo
120      * {
121      *   ...
122      *   private:
123      *     // Implementation class
124      *     struct Impl;
125      *     // Pointer to implementation; actually a shared_ptr<Impl>
126      *     RW_pointer<Impl> _pimpl;
127      *
128      *     void baa()       { _pimpl->... } // is Impl *
129      *     void baa() const { _pimpl->... } // is Impl const *
130      * };
131      * \endcode
132     */
133     template<class _D, class _Traits = rw_pointer::Shared<_D> >
134       struct RW_pointer
135       {
136         typedef typename _Traits::_Ptr               _Ptr;
137         typedef typename _Traits::_constPtr          _constPtr;
138         typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
139
140         explicit
141         RW_pointer( typename _Ptr::element_type * dptr = 0 )
142         : _dptr( dptr )
143         {}
144
145         explicit
146         RW_pointer( _Ptr dptr )
147         : _dptr( dptr )
148         {}
149
150         void reset()
151         { _dptr.reset(); }
152
153         void reset( typename _Ptr::element_type * dptr )
154         { _dptr.reset( dptr ); }
155
156         void swap( RW_pointer & rhs )
157         { _dptr.swap( rhs._dptr ); }
158
159         void swap( _Ptr & rhs )
160         { _dptr.swap( rhs ); }
161
162         operator unspecified_bool_type() const
163         { return _dptr; }
164
165         const _D & operator*() const
166         { return *_dptr; };
167
168         const _D * operator->() const
169         { return _dptr.get(); }
170
171         const _D * get() const
172         { return _dptr.get(); }
173
174         _D & operator*()
175         { return *_dptr; }
176
177         _D * operator->()
178         { return _dptr.get(); }
179
180         _D * get()
181         { return _dptr.get(); }
182
183       public:
184         bool      unique() const
185         { return _dptr.unique(); }
186
187         long      use_count() const
188         { return _dptr.use_count(); }
189
190         _constPtr getPtr() const
191         { return _dptr; }
192
193         _Ptr getPtr()
194         { return _dptr; }
195
196       private:
197         _Ptr _dptr;
198       };
199     ///////////////////////////////////////////////////////////////////
200
201     /** \relates RW_pointer Stream output.
202      *
203      * Print the \c _D object the RW_pointer refers, or \c "NULL"
204      * if the pointer is \c NULL.
205     */
206     template<class _D, class _Ptr>
207       inline std::ostream &
208       operator<<( std::ostream & str, const RW_pointer<_D, _Ptr> & obj )
209       {
210         if ( obj.get() )
211           return str << *obj.get();
212         return str << std::string("NULL");
213       }
214
215     ///////////////////////////////////////////////////////////////////
216
217     ///////////////////////////////////////////////////////////////////
218     //
219     //  CLASS NAME : RWCOW_pointer
220     //
221     /** \ref RW_pointer supporting 'copy on write' functionality.
222      *
223      * \em Write access to the underlying object creates a copy, iff
224      * the object is shared.
225      *
226      * See \ref RW_pointer.
227     */
228     template<class _D, class _Traits = rw_pointer::Shared<_D> >
229       struct RWCOW_pointer
230       {
231         typedef typename _Traits::_Ptr               _Ptr;
232         typedef typename _Traits::_constPtr          _constPtr;
233         typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
234
235         explicit
236         RWCOW_pointer( typename _Ptr::element_type * dptr = 0 )
237         : _dptr( dptr )
238         {}
239
240         explicit
241         RWCOW_pointer( _Ptr dptr )
242         : _dptr( dptr )
243         {}
244
245         void reset()
246         { _dptr.reset(); }
247
248         void reset( typename _Ptr::element_type * dptr )
249         { _dptr.reset( dptr ); }
250
251         void swap( RWCOW_pointer & rhs )
252         { _dptr.swap( rhs._dptr ); }
253
254         void swap( _Ptr & rhs )
255         { _dptr.swap( rhs ); }
256
257         operator unspecified_bool_type() const
258         { return _dptr; }
259
260         const _D & operator*() const
261         { return *_dptr; };
262
263         const _D * operator->() const
264         { return _dptr.get(); }
265
266         const _D * get() const
267         { return _dptr.get(); }
268
269         _D & operator*()
270         { assertUnshared(); return *_dptr; }
271
272         _D * operator->()
273         { assertUnshared(); return _dptr.get(); }
274
275         _D * get()
276         { assertUnshared(); return _dptr.get(); }
277
278       public:
279         _constPtr getPtr() const
280         { return _dptr; }
281
282         _Ptr getPtr()
283         { assertUnshared(); return _dptr; }
284
285       private:
286
287         void assertUnshared()
288         {
289           if ( _Traits().isShared( _dptr ) )
290             {
291               _dptr.reset( rwcowClone( _dptr.get() ) );
292             }
293         }
294
295       private:
296         _Ptr _dptr;
297       };
298     ///////////////////////////////////////////////////////////////////
299
300     /** \relates RWCOW_pointer Clone the underlying object.
301      * Calls \a rhs <tt>-\>clone()</tt>. Being defined as a
302      * function outside \ref RWCOW_pointer allows to overload
303      * it, in case a specific \a _D does not have <tt>clone()</tt>.
304     */
305     template<class _D>
306       inline _D * rwcowClone( const _D * rhs )
307       { return rhs->clone(); }
308
309     ///////////////////////////////////////////////////////////////////
310
311     /** \relates RWCOW_pointer Stream output.
312      *
313      * Print the \c _D object the RWCOW_pointer refers, or \c "NULL"
314      * if the pointer is \c NULL.
315     */
316     template<class _D, class _Ptr>
317       inline std::ostream &
318       operator<<( std::ostream & str, const RWCOW_pointer<_D, _Ptr> & obj )
319       {
320         if ( obj.get() )
321           return str << *obj.get();
322         return str << std::string("NULL");
323       }
324
325     ///////////////////////////////////////////////////////////////////
326
327     /*@}*/
328
329   /////////////////////////////////////////////////////////////////
330 } // namespace zypp
331 ///////////////////////////////////////////////////////////////////
332
333 /** Forward declaration of Ptr types */
334 #define DEFINE_PTR_TYPE(NAME) \
335 class NAME;                                                      \
336 extern void intrusive_ptr_add_ref( const NAME * );               \
337 extern void intrusive_ptr_release( const NAME * );               \
338 typedef zypp::intrusive_ptr<NAME>       NAME##_Ptr;        \
339 typedef zypp::intrusive_ptr<const NAME> NAME##_constPtr;
340
341 ///////////////////////////////////////////////////////////////////
342 #endif // ZYPP_BASE_PTRTYPES_H