Imported Upstream version 14.45.0
[platform/upstream/libzypp.git] / examples / COW_debug.cc
1 #include <iosfwd>
2 #include "zypp/base/PtrTypes.h"
3
4 ///////////////////////////////////////////////////////////////////
5 // MyClass.h
6 ///////////////////////////////////////////////////////////////////
7 namespace zypp
8 {
9   ///////////////////////////////////////////////////////////////////
10   /** Simple class using a RWCOW_pointer to implementation.
11    *
12    * MyClass maintains an int value, manipulated via get/set.
13    * RWCOW_pointer provides the 'copy on write' functionality.
14   */
15   class MyClass
16   {
17   public:
18     /** Implementation (public, but hidden in MyClass.cc) */
19     struct Impl;
20
21   public:
22     MyClass( int val = 0 );
23
24     int get() const;
25
26     void set( int val );
27
28   private:
29     /** Pointer to implementation */
30     RWCOW_pointer<Impl> _pimpl;
31   };
32   ///////////////////////////////////////////////////////////////////
33 }
34 ///////////////////////////////////////////////////////////////////
35
36
37
38 ///////////////////////////////////////////////////////////////////
39 // MyClass.cc
40 ///////////////////////////////////////////////////////////////////
41 #include <zypp/base/Debug.h>
42
43 using std::endl;
44
45 namespace zypp
46 {
47   ///////////////////////////////////////////////////////////////////
48   //
49   namespace debug
50   {
51     /** Forward decl. Implemented after MyClass::Impl is defined,
52      * if you want to dynamic_cast TraceCAD<MyClass::Impl> back into
53      * MyClass::Impl. Otherwise you could implement it here.
54      */
55     template<>
56       void traceCAD( TraceCADBase::What what_r,
57                      const TraceCAD<MyClass::Impl> & self_r,
58                      const TraceCAD<MyClass::Impl> & rhs_r );
59   }
60   //
61   ///////////////////////////////////////////////////////////////////
62
63   ///////////////////////////////////////////////////////////////////
64   /** Implementation of MyClass providing the int value.
65    *
66    * To debug via TraceCAD, simply derive. Per default TraceCAD
67    * drops loglines. In this example we overload traceCAD<Impl>,
68    * to do a bit more stuff.
69   */
70   struct MyClass::Impl : public debug::TraceCAD<Impl>
71   {
72     Impl( int val = 0 )
73     : _value( val )
74     {}
75
76     int _value;
77
78   private:
79     friend Impl * rwcowClone<Impl>( const Impl * rhs );
80     /** clone for RWCOW_pointer */
81     Impl * clone() const
82     { return new Impl( *this ); }
83   };
84   ///////////////////////////////////////////////////////////////////
85
86   inline std::ostream & operator<<( std::ostream & str, const MyClass::Impl & obj )
87   { return str << "MyClass::Impl[" << &obj << "] value: " << obj._value; }
88
89   ///////////////////////////////////////////////////////////////////
90
91   ///////////////////////////////////////////////////////////////////
92   // class MyClass
93   ///////////////////////////////////////////////////////////////////
94
95   MyClass::MyClass( int val )
96   : _pimpl( new Impl( val ) )
97   {
98     // e.g _PING to indicate ctor is done.
99     _pimpl->_PING();
100   }
101
102   /** Impl access via 'operator->() const' (readonly) */
103   int MyClass::get() const
104   { return _pimpl->_value; }
105
106   /** Impl access via 'operator->()' (write, creates a copy iff shared) */
107   void MyClass::set( int val )
108   { _pimpl->_value = val; }
109
110   ///////////////////////////////////////////////////////////////////
111   //
112   namespace debug
113   {
114     /** Performs all possible casts of self_r/rhs_r back into
115      * MyClass::Impl.
116      *
117      * CTOR,DTOR: self_r can't be casted, because MyClass::Impl
118      * is not yet constructed (TraceCAD is base class), or already
119      * deleted. rhs_r is meaningless (==self_r).
120      *
121      * COPYCTOR: self_r can't be casted (not yet constructed).
122      * rhs_r can be casted into MyClass::Impl. It's the object
123      * we copy from.
124      *
125      * ASSIGN: self_r and rhs_r can be casted. If MyClass::Impl
126      * defines an operator==, you have to alter the code to call
127      * TraceCAD::operator=. Otherwise it won't be triggered.
128      *
129      * PING: self_r can be casted, rhs_r is meaningless (==self_r).
130      * You have to alter MyClass::Impl to call '_PING()' to recieve
131      * the trigger. The only purpose is to provide an easy way to
132      * trigger some action, without much changes to the original code.
133      * Call _PING there and perfrorm the action here, if possible.
134     */
135     template<>
136       void traceCAD( TraceCADBase::What what_r,
137                      const TraceCAD<MyClass::Impl> & self_r,
138                      const TraceCAD<MyClass::Impl> & rhs_r )
139       {
140         static unsigned instanceCouter = 0;
141         // lazy #define ;)
142 #define STATS "\t(total " << instanceCouter << ")"
143
144         switch( what_r )
145           {
146           case TraceCADBase::CTOR:
147             ++instanceCouter;
148             SEC << self_r << what_r << STATS << std::endl;
149             break;
150
151           case TraceCADBase::DTOR:
152             --instanceCouter;
153             SEC << self_r << what_r << STATS << std::endl;
154             break;
155
156           case TraceCADBase::PING:
157             SEC << dynamic_cast<const MyClass::Impl &>(self_r)
158                 << what_r << STATS << std::endl;
159             break;
160
161           case TraceCADBase::COPYCTOR:
162             ++instanceCouter;
163             SEC << self_r << what_r << "( "
164                 << dynamic_cast<const MyClass::Impl &>(rhs_r)
165                 << ")" << STATS << std::endl;
166             break;
167
168           case TraceCADBase::ASSIGN:
169             SEC << dynamic_cast<const MyClass::Impl &>(self_r)
170                 << what_r << "( "
171                 << dynamic_cast<const MyClass::Impl &>(rhs_r)
172                 << ")" << STATS << std::endl;
173             break;
174           }
175       }
176   }
177   //
178   ///////////////////////////////////////////////////////////////////
179 }
180 ///////////////////////////////////////////////////////////////////
181
182 /******************************************************************
183 **
184 **
185 **      FUNCTION NAME : main
186 **      FUNCTION TYPE : int
187 **
188 **      DESCRIPTION :
189 */
190 int main( int argc, char * argv[] )
191 {
192   INT << "===[START]==========================================" << endl;
193   using zypp::MyClass;
194
195   MyClass c; // MyClass::Impl CTOR
196   MyClass d( c ); // shares Impl
197   MyClass e( d ); // shares Impl
198
199   MIL << "c.get" << c.get() << endl;
200   MIL << "d.get" << d.get() << endl;
201   MIL << "e.get" << e.get() << endl;
202
203   DBG << "will d.set( 4 )..." << endl;
204   d.set( 4 ); // performs COW
205   DBG << "done d.set( 4 )" << endl;
206
207   MIL << "c.get" << c.get() << endl;
208   MIL << "d.get" << d.get() << endl;
209   MIL << "e.get" << e.get() << endl;
210
211   DBG << "will e=d..." << endl;
212   e = d; // shares Impl
213   DBG << "done e=d" << endl;
214
215   MIL << "c.get" << c.get() << endl;
216   MIL << "d.get" << d.get() << endl;
217   MIL << "e.get" << e.get() << endl;
218
219   DBG << "will e.set( 1 )..." << endl;
220   e.set( 1 ); // performs COW
221   DBG << "done e.set( c )" << endl;
222
223   MIL << "c.get" << c.get() << endl;
224   MIL << "d.get" << d.get() << endl;
225   MIL << "e.get" << e.get() << endl;
226
227   INT << "===[END]============================================" << endl;
228   return 0;
229   // Tree times MyClass::Impl DTOR
230 }