6b789f2ce4a531dd5e1bf8500bddedaf4602e4ce
[platform/upstream/libzypp.git] / zypp / AutoDispose.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/AutoDispose.h
10  *
11 */
12 #ifndef ZYPP_AUTODISPOSE_H
13 #define ZYPP_AUTODISPOSE_H
14
15 #include <iosfwd>
16 #include <boost/call_traits.hpp>
17
18 #include "zypp/base/NonCopyable.h"
19 #include "zypp/base/PtrTypes.h"
20 #include "zypp/base/Function.h"
21
22 ///////////////////////////////////////////////////////////////////
23 namespace zypp
24 { /////////////////////////////////////////////////////////////////
25
26   ///////////////////////////////////////////////////////////////////
27   //
28   //    CLASS NAME : AutoDispose<_Tp>
29   //
30   /** Reference counted access to a \c _Tp object calling a custom
31    *  \c Dispose function when the last AutoDispose handle to it is
32    *  destroyed or reset.
33    *
34    * \note As with pointers, constness of an \c AutoDispose object does
35    * \b not apply to the stored \c _Tp object. If the stored \c _Tp object
36    * should be immutable, you should use <tt>AutoDispose\<const _Tp\></tt>.
37    *
38    * Pass a filename to the application and provide the appropriate
39    * code to be executed when the file is no longer needed:
40    * \code
41    * struct FileCache
42    * {
43    *   Pathname getFile();
44    *   void     releaseFile( const Pathname & );
45    * };
46    *
47    * static FileCache cache;
48    *
49    * void unlink( const Pathname & file_r );
50    *
51    * AutoDispose<const Pathname> provideFile( ... )
52    * {
53    *   if ( file_is_in_cache )
54    *     {
55    *       // will call 'cache.releaseFile( file )'
56    *       return AutoDispose<const Pathname>( cache.getFile(),
57    *                                           bind( &FileCache::releaseFile, ref(cache), _1 ) );
58    *     }
59    *   else if ( file_is_temporary )
60    *     {
61    *       // will call 'unlink( file )'
62    *       return AutoDispose<const Pathname>( file, unlink );
63    *     }
64    *   else if ( file_is_permanent )
65    *     {
66    *       // will do nothing.
67    *       return AutoDispose<const Pathname>( file );
68    *     }
69    *   else
70    *     {
71    *       // will do nothing.
72    *       return AutoDispose<const Pathname>();
73    *     }
74    * }
75    * \endcode
76    *
77    * Exception safe handling of temporary files:
78    * \code
79    * void provideFileAt( const Pathname & destination )
80    * {
81    *   AutoDispose<const Pathname> guard( destination, unlink );
82    *
83    *   // Any exception here will lead to 'unlink( destination )'
84    *   // ...
85    *
86    *   // On success: reset the dispose function to NOOP.
87    *   guard.resetDispose();
88    * }
89    * \endcode
90   */
91   template<class _Tp>
92     class AutoDispose
93     {
94     public:
95       typedef typename boost::call_traits<_Tp>::param_type       param_type;
96       typedef typename boost::call_traits<_Tp>::reference        reference;
97       typedef typename boost::call_traits<_Tp>::const_reference  const_reference;
98       typedef _Tp                                                value_type;
99       typedef typename boost::call_traits<_Tp>::value_type       result_type;
100
101     public:
102       /** Dispose function signatue. */
103       typedef function<void ( param_type )> Dispose;
104
105     public:
106       /** Default Ctor using default constructed value and no dispose function. */
107       AutoDispose()
108       : _pimpl( new Impl( value_type() ) )
109       {}
110
111       /** Ctor taking dispose function and using default constructed value. */
112       explicit AutoDispose( const Dispose & dispose_r )
113       : _pimpl( new Impl( value_type(), dispose_r ) )
114       {}
115
116       /** Ctor taking value and no dispose function. */
117       explicit AutoDispose( param_type value_r )
118       : _pimpl( new Impl( value_r ) )
119       {}
120
121       /** Ctor taking value and dispose function. */
122       AutoDispose( param_type value_r, const Dispose & dispose_r )
123       : _pimpl( new Impl( value_r, dispose_r ) )
124       {}
125
126     public:
127
128       /** Provide implicit conversion to \c _Tp\&. */
129       operator reference() const
130       { return _pimpl->_value; }
131
132       /** Reference to the \c _Tp object. */
133       reference value() const
134       { return _pimpl->_value; }
135
136       /** Reference to the \c _Tp object. */
137       reference operator*() const
138       { return _pimpl->_value; }
139
140       /** Pointer to the \c _Tp object (asserted to be <tt>!= NULL</tt>). */
141       value_type * operator->() const
142       { return & _pimpl->_value; }
143
144       /** Reset to default Ctor values. */
145       void reset()
146       { AutoDispose().swap( *this ); }
147
148       /** Exchange the contents of two AutoDispose objects. */
149       void swap( AutoDispose & rhs )
150       { _pimpl.swap( rhs._pimpl ); }
151
152     public:
153       /** Return the current dispose function. */
154       const Dispose & getDispose() const
155       { return _pimpl->_dispose; }
156
157       /** Set a new dispose function. */
158       void setDispose( const Dispose & dispose_r )
159       { _pimpl->_dispose = dispose_r; }
160
161       /** Set no dispose function. */
162       void resetDispose()
163       { setDispose( Dispose() ); }
164
165       /** Exchange the dispose function. +*/
166       void swapDispose( Dispose & dispose_r )
167       { _pimpl->_dispose.swap( dispose_r ); }
168
169     private:
170       struct Impl : private base::NonCopyable
171       {
172         Impl( param_type value_r )
173         : _value( value_r )
174         {}
175         Impl( param_type value_r, const Dispose & dispose_r )
176         : _value( value_r )
177         , _dispose( dispose_r )
178         {}
179         ~Impl()
180         {
181           if ( _dispose )
182             try { _dispose( _value ); } catch(...) {}
183         }
184         value_type _value;
185         Dispose    _dispose;
186       };
187
188       shared_ptr<Impl> _pimpl;
189     };
190   ///////////////////////////////////////////////////////////////////
191
192   /** \relates AutoDispose<_Tp> Stream output of the \c _Tp object. */
193   template<class _Tp>
194     inline std::ostream & operator<<( std::ostream & str, const AutoDispose<_Tp> & obj )
195     { return str << obj.value(); }
196
197
198   ///////////////////////////////////////////////////////////////////
199   /// \class AutoFD
200   /// \brief \ref AutoDispose\<int>  calling \c ::close
201   /// \ingroup g_RAII
202   ///////////////////////////////////////////////////////////////////
203   struct AutoFD : public AutoDispose<int>
204   {
205     AutoFD( int fd_r = -1 ) : AutoDispose<int>( fd_r, [] ( int fd_r ) { if ( fd_r != -1 ) ::close( fd_r ); } ) {}
206   };
207
208   ///////////////////////////////////////////////////////////////////
209   /// \class AutoFILE
210   /// \brief \ref AutoDispose\<FILE*> calling \c ::fclose
211   /// \see \ref AutoDispose
212   /// \ingroup g_RAII
213   ///////////////////////////////////////////////////////////////////
214   struct AutoFILE : public AutoDispose<FILE*>
215   {
216     AutoFILE( FILE* file_r = nullptr ) : AutoDispose<FILE*>( file_r, [] ( FILE* file_r ) { if ( file_r ) ::fclose( file_r ); } ) {}
217   };
218
219   ///////////////////////////////////////////////////////////////////
220   /// \class AutoFREE<Tp>
221   /// \brief \ref AutoDispose\<Tp*> calling \c ::free
222   /// \ingroup g_RAII
223   ///////////////////////////////////////////////////////////////////
224   template <typename Tp>
225   struct AutoFREE : public AutoDispose<Tp*>
226   {
227     AutoFREE( Tp* ptr_r = nullptr ) : AutoDispose<Tp*>( ptr_r, [] ( Tp* ptr_r ) { if ( ptr_r ) ::free( ptr_r ); } ) {}
228     AutoFREE( void* ptr_r ) : AutoFREE( static_cast<Tp*>(ptr_r) ) {}
229   };
230
231   template <>
232   struct AutoFREE<void> : public AutoDispose<void*>
233   {
234     AutoFREE( void* ptr_r = nullptr ) : AutoDispose<void*>( ptr_r, [] ( void* ptr_r ) { if ( ptr_r ) ::free( ptr_r ); } ) {}
235   };
236   /////////////////////////////////////////////////////////////////
237 } // namespace zypp
238 ///////////////////////////////////////////////////////////////////
239 #endif // ZYPP_AUTODISPOSE_H