2 #include "zypp/base/PtrTypes.h"
4 ///////////////////////////////////////////////////////////////////
6 ///////////////////////////////////////////////////////////////////
9 ///////////////////////////////////////////////////////////////////
10 /** Simple class using a RWCOW_pointer to implementation.
12 * MyClass maintains an int value, manipulated via get/set.
13 * RWCOW_pointer provides the 'copy on write' functionality.
18 /** Implementation (public, but hidden in MyClass.cc) */
22 MyClass( int val = 0 );
29 /** Pointer to implementation */
30 RWCOW_pointer<Impl> _pimpl;
32 ///////////////////////////////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////
38 ///////////////////////////////////////////////////////////////////
40 ///////////////////////////////////////////////////////////////////
41 #include <zypp/base/Debug.h>
47 ///////////////////////////////////////////////////////////////////
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.
56 void traceCAD( TraceCADBase::What what_r,
57 const TraceCAD<MyClass::Impl> & self_r,
58 const TraceCAD<MyClass::Impl> & rhs_r );
61 ///////////////////////////////////////////////////////////////////
63 ///////////////////////////////////////////////////////////////////
64 /** Implementation of MyClass providing the int value.
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.
70 struct MyClass::Impl : public debug::TraceCAD<Impl>
79 friend Impl * rwcowClone<Impl>( const Impl * rhs );
80 /** clone for RWCOW_pointer */
82 { return new Impl( *this ); }
84 ///////////////////////////////////////////////////////////////////
86 inline std::ostream & operator<<( std::ostream & str, const MyClass::Impl & obj )
87 { return str << "MyClass::Impl[" << &obj << "] value: " << obj._value; }
89 ///////////////////////////////////////////////////////////////////
91 ///////////////////////////////////////////////////////////////////
93 ///////////////////////////////////////////////////////////////////
95 MyClass::MyClass( int val )
96 : _pimpl( new Impl( val ) )
98 // e.g _PING to indicate ctor is done.
102 /** Impl access via 'operator->() const' (readonly) */
103 int MyClass::get() const
104 { return _pimpl->_value; }
106 /** Impl access via 'operator->()' (write, creates a copy iff shared) */
107 void MyClass::set( int val )
108 { _pimpl->_value = val; }
110 ///////////////////////////////////////////////////////////////////
114 /** Performs all possible casts of self_r/rhs_r back into
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).
121 * COPYCTOR: self_r can't be casted (not yet constructed).
122 * rhs_r can be casted into MyClass::Impl. It's the object
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.
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.
136 void traceCAD( TraceCADBase::What what_r,
137 const TraceCAD<MyClass::Impl> & self_r,
138 const TraceCAD<MyClass::Impl> & rhs_r )
140 static unsigned instanceCouter = 0;
142 #define STATS "\t(total " << instanceCouter << ")"
146 case TraceCADBase::CTOR:
148 SEC << self_r << what_r << STATS << std::endl;
151 case TraceCADBase::DTOR:
153 SEC << self_r << what_r << STATS << std::endl;
156 case TraceCADBase::PING:
157 SEC << dynamic_cast<const MyClass::Impl &>(self_r)
158 << what_r << STATS << std::endl;
161 case TraceCADBase::COPYCTOR:
163 SEC << self_r << what_r << "( "
164 << dynamic_cast<const MyClass::Impl &>(rhs_r)
165 << ")" << STATS << std::endl;
168 case TraceCADBase::ASSIGN:
169 SEC << dynamic_cast<const MyClass::Impl &>(self_r)
171 << dynamic_cast<const MyClass::Impl &>(rhs_r)
172 << ")" << STATS << std::endl;
178 ///////////////////////////////////////////////////////////////////
180 ///////////////////////////////////////////////////////////////////
182 /******************************************************************
185 ** FUNCTION NAME : main
186 ** FUNCTION TYPE : int
190 int main( int argc, char * argv[] )
192 INT << "===[START]==========================================" << endl;
195 MyClass c; // MyClass::Impl CTOR
196 MyClass d( c ); // shares Impl
197 MyClass e( d ); // shares Impl
199 MIL << "c.get" << c.get() << endl;
200 MIL << "d.get" << d.get() << endl;
201 MIL << "e.get" << e.get() << endl;
203 DBG << "will d.set( 4 )..." << endl;
204 d.set( 4 ); // performs COW
205 DBG << "done d.set( 4 )" << endl;
207 MIL << "c.get" << c.get() << endl;
208 MIL << "d.get" << d.get() << endl;
209 MIL << "e.get" << e.get() << endl;
211 DBG << "will e=d..." << endl;
212 e = d; // shares Impl
213 DBG << "done e=d" << endl;
215 MIL << "c.get" << c.get() << endl;
216 MIL << "d.get" << d.get() << endl;
217 MIL << "e.get" << e.get() << endl;
219 DBG << "will e.set( 1 )..." << endl;
220 e.set( 1 ); // performs COW
221 DBG << "done e.set( c )" << endl;
223 MIL << "c.get" << c.get() << endl;
224 MIL << "d.get" << d.get() << endl;
225 MIL << "e.get" << e.get() << endl;
227 INT << "===[END]============================================" << endl;
229 // Tree times MyClass::Impl DTOR