- Added RWCOW_pointer (PtrTypes.h): RW_pointer supporting 'copy on write'
authorMichael Andres <ma@suse.de>
Tue, 6 Dec 2005 15:06:02 +0000 (15:06 +0000)
committerMichael Andres <ma@suse.de>
Tue, 6 Dec 2005 15:06:02 +0000 (15:06 +0000)
  functionality.

- Fixed Dependencies to perform COW.

- Added Debug.h: Debuging tools which should not be used in released code.

- Added debug::TraceCAD. Debug aid to trace object creation, assign and
  destruction.

devel/devel.ma/Main.cc
devel/genclass.in
zypp/Dependencies.cc
zypp/Dependencies.h
zypp/Edition.cc
zypp/base/Debug.h [new file with mode: 0644]
zypp/base/Makefile.am
zypp/base/PtrTypes.h
zypp/base/ReferenceCounted.h

index fa06704..3413eba 100644 (file)
-#include <iostream>
-#include <ctime>
-
-#include <fstream>
-#include <list>
-#include <string>
-#include <zypp/base/Logger.h>
-#include <zypp/base/String.h>
-#include <zypp/base/PtrTypes.h>
-
-#include <zypp/CapFactory.h>
-#include <zypp/CapSet.h>
-
-using namespace std;
-using namespace zypp;
-
-// work around flaw in y2logview
-template<class _Tp>
-  void printOnHack( const _Tp & obj )
-  {
-    MIL << obj << endl;
-  };
+#include <iosfwd>
+#include "zypp/base/PtrTypes.h"
 
 ///////////////////////////////////////////////////////////////////
-// Just for the stats
-struct Measure
+// MyClass.h
+///////////////////////////////////////////////////////////////////
+namespace zypp
 {
-  time_t _begin;
-  Measure()
-  : _begin( time(NULL) )
-  {
-    USR << "START MEASURE..." << endl;
-  }
-  ~Measure()
+  ///////////////////////////////////////////////////////////////////
+  class MyClass
+  ///////////////////////////////////////////////////////////////////
   {
-    USR << "DURATION: " << (time(NULL)-_begin) << " sec." << endl;
-  }
-};
-
-///////////////////////////////////////////////////////////////////
-// Print stream status
-ostream & operator<<( ostream & str, const istream & obj ) {
-  return str
-  << (obj.good() ? 'g' : '_')
-  << (obj.eof()  ? 'e' : '_')
-  << (obj.fail() ? 'F' : '_')
-  << (obj.bad()  ? 'B' : '_');
-}
+  public:
+    /** Implementation */
+    struct Impl;
 
-///////////////////////////////////////////////////////////////////
-// Return one line from stream
-std::string getline( std::istream & str )
-{
-  static const unsigned tmpBuffLen = 1024;
-  static char           tmpBuff[tmpBuffLen];
-  string ret;
-  do {
-    str.clear();
-    str.getline( tmpBuff, tmpBuffLen ); // always writes '\0' terminated
-    ret += tmpBuff;
-  } while( str.rdstate() == ios::failbit );
+  public:
+    MyClass( int val = 0 );
 
-  return ret;
-}
+    int get() const;
 
-///////////////////////////////////////////////////////////////////
-// Simple lineparser: Call function do_r for each line.
-template<class _Function>
-  _Function & forEachLine( std::istream & str_r, _Function & do_r )
-  {
-    while ( str_r )
-      {
-        std::string l = getline( str_r );
-        if ( ! (str_r.fail() || str_r.bad()) )
-          {
-            // l contains valid data to be consumed.
-            do_r( l );
-          }
-      }
-    return do_r;
-  }
+    void set( int val );
 
-///////////////////////////////////////////////////////////////////
-// Fits forEachLine. A simple 'do' function
-void collect( const std::string & linre_r )
-{
-  DBG << linre_r << endl;
+  private:
+    /** Pointer to implementation */
+    RWCOW_pointer<Impl> _pimpl;
+  };
+  ///////////////////////////////////////////////////////////////////
 }
 ///////////////////////////////////////////////////////////////////
-// Fits forEachLine. A simple 'do' functor counting lines as base.
-/*
- Line processing is prepared by providing 'virtual void doConsume(std::string)'.
- That's what a derived Collector will overload.
- */
-struct Collector : public std::unary_function<const std::string &, void>
-{
-  unsigned _lineNo;
-  Collector()
-  : _lineNo( 0 )
-  {}
-  virtual ~Collector()
-  {}
-  virtual void doConsume( const std::string & line_r )
-  {}
-  void operator()( const std::string & line_r )
-  {
-    ++_lineNo;
-    if ( ! (_lineNo % 10000) )
-      DBG << "Got " << _lineNo << " lines..." << endl;
-    doConsume( line_r );
-  }
-};
+
+
+
 ///////////////////////////////////////////////////////////////////
-// Fits forEachLine. An impatient collector ;)
-struct ImpatientCollector : public Collector
-{
-  virtual void doConsume( const std::string & line_r )
-  {
-    if ( _lineNo == 1234 )
-      ZYPP_THROW( "takes to long" );
-  }
-};
+// MyClass.cc
 ///////////////////////////////////////////////////////////////////
-// Fits forEachLine. Almost usefull collector.
-/*
- Note that it's still a functor 'void operator()( const std::string & )'.
+#include <zypp/base/Debug.h>
 
- On every invocation the string is parsed into a Capability, and the
- Capability is stored in a CapSet.
+using std::endl;
 
- Exceptions building the Capability are caught and collected in a
- Failure list. It's a matter of taste whether to immediately abort,
- or to parse to the end check for collected errors then. Room for
- improvement.
-
- see enhacedCollectorUsage().
-*/
-struct EnhacedCollector : public Collector
+namespace zypp
 {
-  // Stores line number, original string and Exception
-  struct Failure
+  ///////////////////////////////////////////////////////////////////
+  struct MyClass::Impl : public debug::TraceCAD<Impl>
+  ///////////////////////////////////////////////////////////////////
   {
-    unsigned _lineNo;
-    std::string _line;
-    Exception _excpt;
-    Failure( unsigned lineNo_r,
-             const std::string & line_r, const Exception & excpt_r )
-    : _lineNo( lineNo_r ), _line( line_r ), _excpt( excpt_r )
+    Impl( int val = 0 )
+    : _value( val )
     {}
-  };
 
-  typedef std::list<Failure> FailedList;
+    int _value;
 
-  CapFactory  _factory;
-  unsigned    _capLines;
-  CapSet      _caps;
-  FailedList  _failures;
+  private:
+    friend Impl * rwcowClone<Impl>( const Impl * rhs );
+    /** clone for RWCOW_pointer */
+    Impl * clone() const
+    { return new Impl( *this ); }
+  };
+  ///////////////////////////////////////////////////////////////////
 
+  ///////////////////////////////////////////////////////////////////
+  // class MyClass
+  ///////////////////////////////////////////////////////////////////
 
-  EnhacedCollector()
-  : _capLines( 0 )
+  MyClass::MyClass( int val )
+  : _pimpl( new Impl( val ) )
   {}
 
-  void makeCap( const string & line_r )
-  {
-    ++_capLines; // count attempts
-    try
-      {
-        // bulid Package deps.
-        _caps.insert( _factory.parse( ResTraits<Package>::kind, line_r ) );
-      }
-    catch( Exception & excpt_r )
-      {
-        _failures.push_back( Failure(_lineNo, line_r, excpt_r) );
-      }
-  }
+  int MyClass::get() const
+  { return _pimpl->_value; }
 
-  virtual void doConsume( const std::string & line_r )
-  {
-    makeCap( line_r );
-  }
-};
+  void MyClass::set( int val )
+  { _pimpl->_value = val; }
 
-// Print a Failure
-ostream & operator<<( ostream & str, const EnhacedCollector::Failure & obj )
-{
-  return str << str::form( "[%u] \"%s\" ==> %s",
-                           obj._lineNo,
-                           obj._line.c_str(),
-                           obj._excpt.asString().c_str() );
-}
-
-// Print EnhacedCollector stats
-ostream & operator<<( ostream & str, const EnhacedCollector & obj )
-{
-  str << "Lines parsed : " << obj._lineNo << endl;
-  str << "Cap lines    : " << obj._capLines << endl;
-  str << "Capabilites  : " << obj._caps.size() << endl;
-  str << "Parse errors : " << obj._failures.size() << endl;
-  if ( obj._failures.size() )
-    {
-      copy( obj._failures.begin(), obj._failures.end(),
-            ostream_iterator<EnhacedCollector::Failure>(ERR,"\n") );
-      //-something-we-should-not-do-unless-....---------^^^
-    }
-  return str;
 }
-
 ///////////////////////////////////////////////////////////////////
-// Fits forEachLine.
-/*
- Within a packages file, not every line defines a Capability. So
- EnhacedCollector is refined to turn Capability collection on and
- off, as appropriate. A dumb version simply storing all Capabilities
- defined somewhere in the packages file.
-*/
-struct PackageParseCollector : public EnhacedCollector
-{
-  static std::string _rxStrDeps;
-  static str::regex  _rxDepOn;
-  static str::regex  _rxDepOff;
-
-  str::smatch _what;
-  bool        _consume;
-
-  PackageParseCollector()
-  : _consume( false )
-  {}
-
-  bool matches( const string & line_r, const str::regex & rx_r )
-  {
-    return str::regex_match( line_r.begin(), line_r.end(), rx_r );
-  }
-
-  virtual void doConsume( const std::string & line_r )
-  {
-    if ( _consume )
-      {
-        if ( matches( line_r, _rxDepOff ) )
-          {
-            _consume = false;
-          }
-        else
-          {
-            EnhacedCollector::doConsume( line_r );
-          }
-      }
-    else if ( matches( line_r, _rxDepOn ) )
-      {
-        _consume = true;
-      }
-  }
-};
-
-std::string PackageParseCollector::_rxStrDeps( "(Req|Prq|Prv|Con|Obs)" );
-str::regex  PackageParseCollector::_rxDepOn ( str::form( "\\+%s:", _rxStrDeps.c_str() ) );
-str::regex  PackageParseCollector::_rxDepOff( str::form( "-%s:", _rxStrDeps.c_str() ) );
 
 /******************************************************************
 **
-**      FUNCTION NAME : enhacedCollectorUsage
-**      FUNCTION TYPE :
-*/
-void enhacedCollectorUsage()
-{
-  // EnhacedCollector: Simply collect strings which are expected to
-  // be Capabilities. Error handling is delayed by collecting failures.
-  EnhacedCollector collector;
-  collector( "" );
-  collector( "foo baa kaa" );
-  collector( "/bin/sh" );
-  collector( "/bin/sh" );
-  collector( "/bin/sh" );
-  collector( "/bin/sh" );
-
-  MIL << collector << endl;
-  MIL << "Capabilities found:" << endl;
-  for_each( collector._caps.begin(), collector._caps.end(),
-            printOnHack<Capability> );
-}
-
-/******************************************************************
 **
 **      FUNCTION NAME : main
 **      FUNCTION TYPE : int
+**
+**      DESCRIPTION :
 */
 int main( int argc, char * argv[] )
 {
-  string file( "packages" );
-
   INT << "===[START]==========================================" << endl;
+  using zypp::MyClass;
+
+  MyClass c;
+  MyClass d( c );
+  MyClass e( d );
 
-  // dump PackageParseCollector: open the file, and build Capabilities
-  // from each appropriate line. Collecting failures.
+  MIL << "c.get" << c.get() << endl;
+  MIL << "d.get" << d.get() << endl;
+  MIL << "e.get" << e.get() << endl;
 
-  ifstream str( file.c_str() );
-  (str?DBG:ERR) << file << ": " << str << endl;
-  shared_ptr<Measure> duration( new Measure );
+  DBG << "will d.set( 4 )..." << endl;
+  d.set( 4 );
+  DBG << "done d.set( 4 )" << endl;
 
-  PackageParseCollector datacollect;
-  try
-    {
-      forEachLine( str, datacollect );
-    }
-  catch ( Exception & excpt_r )
-    {
-      // Note: Exceptions building a Capability are caught. So this is
-      // something different. Maybe a bored ImpatientCollector.
-      ZYPP_CAUGHT( excpt_r );
-      ERR << "Parse error at line " << datacollect._lineNo << ": " << excpt_r << endl;
-      return 1;
-    }
+  MIL << "c.get" << c.get() << endl;
+  MIL << "d.get" << d.get() << endl;
+  MIL << "e.get" << e.get() << endl;
 
-  duration.reset();
-  DBG << file << ": " << str << endl;
+  DBG << "will d.set( 5 )..." << endl;
+  d.set( 5 );
+  DBG << "done d.set( 5 )" << endl;
 
-  MIL << datacollect << endl;
-  MIL << CapFactory() << endl;
+  MIL << "c.get" << c.get() << endl;
+  MIL << "d.get" << d.get() << endl;
+  MIL << "e.get" << e.get() << endl;
 
-  //MIL << "Capabilities found:" << endl;
-  //for_each( datacollect._caps.begin(), datacollect._caps.end(),
-  //          printOnHack<Capability> );
+  DBG << "will c.set( 1 )..." << endl;
+  c.set( 5 );
+  DBG << "done c.set( c )" << endl;
+
+  MIL << "c.get" << c.get() << endl;
+  MIL << "d.get" << d.get() << endl;
+  MIL << "e.get" << e.get() << endl;
 
   INT << "===[END]============================================" << endl;
   return 0;
 }
+
+#if 0
+
+///////////////////////////////////////////////////////////////////
+namespace zypp
+{ /////////////////////////////////////////////////////////////////
+  ///////////////////////////////////////////////////////////////////
+  namespace debug
+  { /////////////////////////////////////////////////////////////////
+
+    template<>
+      void watchCAD( WatchCADBase::What what_r,
+                     const WatchCAD<Dependencies::Impl> & self_r,
+                     const WatchCAD<Dependencies::Impl> & rhs_r )
+      {
+        switch( what_r )
+          {
+          case WatchCADBase::CTOR:
+          case WatchCADBase::DTOR:
+            SEC << self_r << what_r << std::endl;
+            break;
+          case WatchCADBase::COPYCTOR:
+          case WatchCADBase::ASSIGN:
+            SEC << self_r << what_r << "( "
+            << dynamic_cast<const Dependencies::Impl &>(rhs_r)
+            << ")" << std::endl;
+            break;
+          }
+      }
+
+    /////////////////////////////////////////////////////////////////
+  } // namespace debug
+  ///////////////////////////////////////////////////////////////////
+  /////////////////////////////////////////////////////////////////
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
+#endif
index b7ddb38..a29c220 100644 (file)
@@ -104,13 +104,6 @@ $(intro $CLASS_H)
 #include "zypp/base/PtrTypes.h"
 
 $(nsopen)
-${INDENT}///////////////////////////////////////////////////////////////////
-${INDENT}namespace detail
-${INDENT}{ /////////////////////////////////////////////////////////////////
-${INDENT}  DEFINE_PTR_TYPE(${CLASS}Impl)
-${INDENT}  /////////////////////////////////////////////////////////////////
-${INDENT}} // namespace detail
-${INDENT}///////////////////////////////////////////////////////////////////
 
 ${INDENT}///////////////////////////////////////////////////////////////////
 ${INDENT}//
@@ -119,26 +112,27 @@ ${INDENT}//
 ${INDENT}/** */
 ${INDENT}class ${CLASS}
 ${INDENT}{
+${INDENT}  friend std::ostream & operator<<( std::ostream & str, const ${CLASS} & obj )
+${INDENT}public:
+${INDENT}  /** Implementation  */
+${INDENT}  class Impl;
+
 ${INDENT}public:
 ${INDENT}  /** Default ctor */
 ${INDENT}  ${CLASS}();
-${INDENT}  /** Factory ctor */
-${INDENT}  explicit
-${INDENT}  ${CLASS}( detail::${CLASS}ImplPtr impl_r );
 ${INDENT}  /** Dtor */
 ${INDENT}  ~${CLASS}();
 
+${INDENT}public:
+
 ${INDENT}private:
 ${INDENT}  /** Pointer to implementation */
-${INDENT}  detail::${CLASS}ImplPtr _pimpl;
-${INDENT}public:
-${INDENT}  /** Avoid a bunch of friend decl. */
-${INDENT}  detail::const${CLASS}ImplPtr sayFriend() const;
+${INDENT}  RWCOW_pointer<Impl> _pimpl;
 ${INDENT}};
 ${INDENT}///////////////////////////////////////////////////////////////////
 
 ${INDENT}/** \relates ${CLASS} Stream output */
-${INDENT}extern std::ostream & operator<<( std::ostream & str, const ${CLASS} & obj );
+${INDENT}std::ostream & operator<<( std::ostream & str, const ${CLASS} & obj );
 
 $(nsclose)
 #endif // $INCLUDE_DEF
@@ -151,45 +145,49 @@ function genCC() {
 cat <<EOF
 $(intro $CLASS_CC)
 #include <iostream>
+//#include "zypp/base/Logger.h"
 
-#include "zypp/base/ReferenceCounted.h"
-#include "zypp/base/NonCopyable.h"
 #include "${INCLUDE_H}"
 
-using namespace std;
+using std::endl;
 
 $(nsopen)
 
 ${INDENT}///////////////////////////////////////////////////////////////////
-${INDENT}namespace detail
-${INDENT}{ /////////////////////////////////////////////////////////////////
-
-${INDENT}  ///////////////////////////////////////////////////////////////////
-${INDENT}  //
-${INDENT}  //  CLASS NAME : ${CLASS}Impl
-${INDENT}  //
-${INDENT}  /** ${CLASS} implementation */
-${INDENT}  struct ${CLASS}Impl : public base::ReferenceCounted, private base::NonCopyable
-${INDENT}  {
-${INDENT}    /** Default ctor*/
-${INDENT}    ${CLASS}Impl();
-${INDENT}    /** Dtor */
-${INDENT}    ~${CLASS}Impl();
-${INDENT}  };
-${INDENT}  ///////////////////////////////////////////////////////////////////
-${INDENT}  IMPL_PTR_TYPE(${CLASS}Impl)
-${INDENT}  ///////////////////////////////////////////////////////////////////
-
-${INDENT}  /** \relates ${CLASS}Impl Stream output */
-${INDENT}  inline std::ostream & operator<<( std::ostream & str, const ${CLASS}Impl & obj )
-${INDENT}  {
-${INDENT}    return str << "${CLASS}Impl";
-${INDENT}  }
-
-${INDENT}  /////////////////////////////////////////////////////////////////
-${INDENT}} // namespace detail
+${INDENT}//
+${INDENT}//    CLASS NAME : ${CLASS}::Impl
+${INDENT}//
+${INDENT}/** ${CLASS} implementation. */
+${INDENT}struct ${CLASS}::Impl
+${INDENT}{
+
+${INDENT}public:
+${INDENT}  /** Offer default Impl. */
+${INDENT}  static shared_ptr<Impl> nullimpl()
+${INDENT}  { if ( ! _nullimpl ) _nullimpl.reset( new Impl ); return _nullimpl; }
+
+${INDENT}private:
+${INDENT}  /** Default Impl. */
+${INDENT}  static shared_ptr<Impl> _nullimpl;
+
+${INDENT}private:
+${INDENT}  friend Impl * rwcowClone<Impl>( const Impl * rhs );
+${INDENT}  /** clone for RWCOW_pointer */
+${INDENT}  Impl * clone() const
+${INDENT}  { return new Impl( *this ); }
+${INDENT}};
+${INDENT}///////////////////////////////////////////////////////////////////
+
+${INDENT}shared_ptr<${CLASS}::Impl> ${CLASS}::Impl::_nullimpl;
+
 ${INDENT}///////////////////////////////////////////////////////////////////
 
+${INDENT}/** \relates ${CLASS}::Impl Stream output */
+${INDENT}inline std::ostream & operator<<( std::ostream & str, const ${CLASS}::Impl & obj )
+${INDENT}{
+${INDENT}  return str << "${CLASS}::Impl";
+${INDENT}}
+
 ${INDENT}///////////////////////////////////////////////////////////////////
 ${INDENT}//
 ${INDENT}//    CLASS NAME : ${CLASS}
@@ -202,15 +200,7 @@ ${INDENT}//        METHOD NAME : ${CLASS}::${CLASS}
 ${INDENT}//    METHOD TYPE : Ctor
 ${INDENT}//
 ${INDENT}${CLASS}::${CLASS}()
-${INDENT}{}
-
-${INDENT}///////////////////////////////////////////////////////////////////
-${INDENT}//
-${INDENT}//    METHOD NAME : ${CLASS}::${CLASS}
-${INDENT}//    METHOD TYPE : Ctor
-${INDENT}//
-${INDENT}${CLASS}::${CLASS}( detail::${CLASS}ImplPtr impl_r )
-${INDENT}: _pimpl( impl_r )
+${INDENT}: _pimpl( Impl::nullimpl() )
 ${INDENT}{}
 
 ${INDENT}///////////////////////////////////////////////////////////////////
@@ -221,14 +211,6 @@ ${INDENT}//
 ${INDENT}${CLASS}::~${CLASS}()
 ${INDENT}{}
 
-${INDENT}///////////////////////////////////////////////////////////////////
-${INDENT}//
-${INDENT}//    METHOD NAME : ${CLASS}::sayFriend
-${INDENT}//    METHOD TYPE : detail::const${CLASS}ImplPtr
-${INDENT}//
-${INDENT}detail::const${CLASS}ImplPtr ${CLASS}::sayFriend() const
-${INDENT}{ return _pimpl; }
-
 ${INDENT}/******************************************************************
 ${INDENT}**
 ${INDENT}**    FUNCTION NAME : operator<<
@@ -236,7 +218,7 @@ ${INDENT}** FUNCTION TYPE : std::ostream &
 ${INDENT}*/
 ${INDENT}std::ostream & operator<<( std::ostream & str, const ${CLASS} & obj )
 ${INDENT}{
-${INDENT}  return str << *obj.sayFriend();
+${INDENT}  return str << *obj._pimpl;
 ${INDENT}}
 
 $(nsclose)
index fdd4ab4..98ffdde 100644 (file)
 #include "zypp/Dependencies.h"
 #include "zypp/CapSet.h"
 
-using namespace std;
+using std::endl;
 
 ///////////////////////////////////////////////////////////////////
 namespace zypp
 { /////////////////////////////////////////////////////////////////
 
   ///////////////////////////////////////////////////////////////////
-  namespace detail
-  { /////////////////////////////////////////////////////////////////
-
-    ///////////////////////////////////////////////////////////////////
-    //
-    // CLASS NAME : DependenciesImpl
-    //
-    /** Dependencies implementation */
-    struct DependenciesImpl : public base::ReferenceCounted, private base::NonCopyable
-    {
-      /**  */
-      CapSet _provides;
-      /**  */
-      CapSet _prerequires;
-      /**  */
-      CapSet _requires;
-      /**  */
-      CapSet _conflicts;
-      /**  */
-      CapSet _obsoletes;
-      /**  */
-      CapSet _recommends;
-      /**  */
-      CapSet _suggests;
-      /**  */
-      CapSet _freshens;
-
-      static DependenciesImpl_Ptr nodeps()
-      {
-        if ( !_nodeps ) { _nodeps = new DependenciesImpl; _nodeps->ref(); }
-        return _nodeps;
-      }
-
-    private:
-      static DependenciesImpl_Ptr _nodeps;
-    };
-    ///////////////////////////////////////////////////////////////////
-    IMPL_PTR_TYPE(DependenciesImpl)
-    DependenciesImpl_Ptr DependenciesImpl::_nodeps;
-    ///////////////////////////////////////////////////////////////////
-
-    /** \relates DependenciesImpl Stream output */
-    inline std::ostream & operator<<( std::ostream & str, const DependenciesImpl & obj )
-    {
-      str << "PROVIDES:" << endl << obj._provides;
-      str << "PREREQUIRES:" << endl << obj._prerequires;
-      str << "REQUIRES:" << endl << obj._requires;
-      str << "CONFLICTS:" << endl << obj._conflicts;
-      str << "OBSOLETES:" << endl << obj._obsoletes;
-      str << "RECOMMENDS:" << endl << obj._recommends;
-      str << "SUGGESTS:" << endl << obj._suggests;
-      str << "FRESHENS:" << endl << obj._freshens;
-      return str;
-    }
-
-    /////////////////////////////////////////////////////////////////
-  } // namespace detail
+  //
+  //   CLASS NAME : Dependencies::Impl
+  //
+  /** Dependencies implementation. */
+  struct Dependencies::Impl
+  {
+    /**  */
+    CapSet _provides;
+    /**  */
+    CapSet _prerequires;
+    /**  */
+    CapSet _requires;
+    /**  */
+    CapSet _conflicts;
+    /**  */
+    CapSet _obsoletes;
+    /**  */
+    CapSet _recommends;
+    /**  */
+    CapSet _suggests;
+    /**  */
+    CapSet _freshens;
+
+  public:
+    /** Offer default Impl. */
+    static shared_ptr<Impl> nullimpl()
+    { if ( ! _nullimpl ) _nullimpl.reset( new Impl ); return _nullimpl; }
+
+  private:
+    /** Default Impl: empty sets. */
+    static shared_ptr<Impl> _nullimpl;
+
+  private:
+    friend Impl * rwcowClone<Impl>( const Impl * rhs );
+    /** clone for RWCOW_pointer */
+    Impl * clone() const
+    { return new Impl( *this ); }
+  };
   ///////////////////////////////////////////////////////////////////
 
+  shared_ptr<Dependencies::Impl> Dependencies::Impl::_nullimpl;
+
   ///////////////////////////////////////////////////////////////////
-  //
-  //   CLASS NAME : Dependencies
-  //
+
+  /** \relates DependenciesImpl Stream output */
+  inline std::ostream & operator<<( std::ostream & str, const Dependencies::Impl & obj )
+  {
+    str << "PROVIDES:"    << endl << obj._provides;
+    str << "PREREQUIRES:" << endl << obj._prerequires;
+    str << "REQUIRES:"    << endl << obj._requires;
+    str << "CONFLICTS:"   << endl << obj._conflicts;
+    str << "OBSOLETES:"   << endl << obj._obsoletes;
+    str << "RECOMMENDS:"  << endl << obj._recommends;
+    str << "SUGGESTS:"    << endl << obj._suggests;
+    str << "FRESHENS:"    << endl << obj._freshens;
+    return str;
+  }
   ///////////////////////////////////////////////////////////////////
 
   ///////////////////////////////////////////////////////////////////
   //
-  //   METHOD NAME : Dependencies::Dependencies
-  //   METHOD TYPE : Ctor
+  //   CLASS NAME : Dependencies
   //
-  Dependencies::Dependencies()
-  : _pimpl( detail::DependenciesImpl::nodeps() )
-  {}
+  ///////////////////////////////////////////////////////////////////
 
   ///////////////////////////////////////////////////////////////////
   //
   //   METHOD NAME : Dependencies::Dependencies
   //   METHOD TYPE : Ctor
   //
-  Dependencies::Dependencies( detail::DependenciesImpl_Ptr impl_r )
-  : _pimpl( impl_r ? impl_r : detail::DependenciesImpl::nodeps() )
+  Dependencies::Dependencies()
+  : _pimpl( Impl::nullimpl() )
   {}
 
   ///////////////////////////////////////////////////////////////////
@@ -114,14 +105,6 @@ namespace zypp
   Dependencies::~Dependencies()
   {}
 
-  ///////////////////////////////////////////////////////////////////
-  //
-  //   METHOD NAME : Dependencies::sayFriend
-  //   METHOD TYPE : detail::DependenciesImplconstPtr
-  //
-  detail::DependenciesImpl_constPtr Dependencies::sayFriend() const
-  { return _pimpl; }
-
   const CapSet & Dependencies::provides() const
   { return _pimpl->_provides; }
 
@@ -146,44 +129,29 @@ namespace zypp
   const CapSet & Dependencies::freshens() const
   { return _pimpl->_freshens; }
 
-#define ZYPP_DEPENDENCIES_COW \
-if(_pimpl->refCount()>1) \
-{ \
-  detail::DependenciesImpl_Ptr _cow_tmp = new detail::DependenciesImpl; \
-  _cow_tmp->_provides = _pimpl->_provides; \
-  _cow_tmp->_prerequires = _pimpl->_prerequires; \
-  _cow_tmp->_requires = _pimpl->_requires; \
-  _cow_tmp->_conflicts = _pimpl->_conflicts; \
-  _cow_tmp->_obsoletes = _pimpl->_obsoletes; \
-  _cow_tmp->_recommends = _pimpl->_recommends; \
-  _cow_tmp->_suggests = _pimpl->_suggests; \
-  _cow_tmp->_freshens = _pimpl->_freshens; \
-  _pimpl= _cow_tmp;\
-}
-
   void Dependencies::setProvides( const CapSet & val_r )
-  { ZYPP_DEPENDENCIES_COW; _pimpl->_provides = val_r; }
+  { _pimpl->_provides = val_r; }
 
   void Dependencies::setPrerequires( const CapSet & val_r )
-  { ZYPP_DEPENDENCIES_COW; _pimpl->_prerequires = val_r; }
+  { _pimpl->_prerequires = val_r; }
 
   void Dependencies::setRequires( const CapSet & val_r )
-  { ZYPP_DEPENDENCIES_COW; _pimpl->_requires = val_r; }
+  { _pimpl->_requires = val_r; }
 
   void Dependencies::setConflicts( const CapSet & val_r )
-  { ZYPP_DEPENDENCIES_COW; _pimpl->_conflicts = val_r; }
+  { _pimpl->_conflicts = val_r; }
 
   void Dependencies::setObsoletes( const CapSet & val_r )
-  { ZYPP_DEPENDENCIES_COW; _pimpl->_obsoletes = val_r; }
+  { _pimpl->_obsoletes = val_r; }
 
   void Dependencies::setRecommends( const CapSet & val_r )
-  { ZYPP_DEPENDENCIES_COW; _pimpl->_recommends = val_r; }
+  { _pimpl->_recommends = val_r; }
 
   void Dependencies::setSuggests( const CapSet & val_r )
-  { ZYPP_DEPENDENCIES_COW; _pimpl->_suggests = val_r; }
+  { _pimpl->_suggests = val_r; }
 
   void Dependencies::setFreshens( const CapSet & val_r )
-  { ZYPP_DEPENDENCIES_COW; _pimpl->_freshens = val_r; }
+  { _pimpl->_freshens = val_r; }
 
   /******************************************************************
   **
@@ -192,7 +160,7 @@ if(_pimpl->refCount()>1) \
   */
   std::ostream & operator<<( std::ostream & str, const Dependencies & obj )
   {
-    return str << *obj.sayFriend();
+    return str << *obj._pimpl;
   }
 
   /////////////////////////////////////////////////////////////////
index 4967dd4..6fb7464 100644 (file)
 ///////////////////////////////////////////////////////////////////
 namespace zypp
 { /////////////////////////////////////////////////////////////////
-  ///////////////////////////////////////////////////////////////////
-  namespace detail
-  { /////////////////////////////////////////////////////////////////
-    DEFINE_PTR_TYPE(DependenciesImpl)
-    /////////////////////////////////////////////////////////////////
-  } // namespace detail
-  ///////////////////////////////////////////////////////////////////
 
   ///////////////////////////////////////////////////////////////////
   //
   //   CLASS NAME : Dependencies
   //
-  /** */
+  /**
+   * \invariant No NULL _pimpl.
+  */
   class Dependencies
   {
+    friend std::ostream & operator<<( std::ostream & str, const Dependencies & obj );
+  public:
+
+    /** Implementation */
+    struct Impl;
+
   public:
     /** Default ctor */
     Dependencies();
-    /** Factory ctor */
-    explicit
-    Dependencies( detail::DependenciesImpl_Ptr impl_r );
     /** Dtor */
     ~Dependencies();
 
@@ -82,10 +80,7 @@ namespace zypp
 
   private:
     /** Pointer to implementation */
-    detail::DependenciesImpl_Ptr _pimpl;
-  public:
-    /** Avoid a bunch of friend decl. */
-    detail::DependenciesImpl_constPtr sayFriend() const;
+    RWCOW_pointer<Impl> _pimpl;
   };
   ///////////////////////////////////////////////////////////////////
 
index d58cf93..d622843 100644 (file)
@@ -134,7 +134,9 @@ namespace zypp
   //
   //   CLASS NAME : Edition::Impl
   //
-  /** Edition implementation */
+  /** Edition implementation.
+   * \todo Unifiy Impl in Edition::noedition and Edition::Edition()
+  */
   struct Edition::Impl
   {
     Impl()
diff --git a/zypp/base/Debug.h b/zypp/base/Debug.h
new file mode 100644 (file)
index 0000000..cc77261
--- /dev/null
@@ -0,0 +1,96 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file      zypp/base/Debug.h
+ *
+ * Debuging tools which should not be used in released code.
+*/
+#warning ZYPP_BASE_DEBUG_H included
+#ifndef ZYPP_BASE_DEBUG_H
+#define ZYPP_BASE_DEBUG_H
+
+#include <iostream>
+#include "zypp/base/Logger.h"
+#include "zypp/base/PtrTypes.h"
+
+///////////////////////////////////////////////////////////////////
+namespace zypp
+{ /////////////////////////////////////////////////////////////////
+  ///////////////////////////////////////////////////////////////////
+  namespace debug
+  { /////////////////////////////////////////////////////////////////
+
+#define TAG INT << __PRETTY_FUNCTION__ << std::endl
+
+    ///////////////////////////////////////////////////////////////////
+    struct TraceCADBase
+    {
+      enum What { CTOR, COPYCTOR, ASSIGN, DTOR, PING };
+    };
+
+    inline std::ostream & operator<<( std::ostream & str, const TraceCADBase & obj )
+    { return str << "TraceCAD[" << &obj << "] "; }
+
+    inline std::ostream & operator<<( std::ostream & str, TraceCADBase::What obj )
+    {
+      switch( obj )
+        {
+        case TraceCADBase::CTOR:     return str << "CTOR";
+        case TraceCADBase::COPYCTOR: return str << "COPYCTOR";
+        case TraceCADBase::ASSIGN:   return str << "ASSIGN";
+        case TraceCADBase::DTOR:     return str << "DTOR";
+        case TraceCADBase::PING:     return str << "PING";
+        }
+      return str;
+    }
+
+    template<class _Tp>
+      struct TraceCAD : public TraceCADBase
+      {
+        TraceCAD()
+        { traceCAD( CTOR, *this, *this ); }
+
+        TraceCAD( const TraceCAD & rhs )
+        { traceCAD( COPYCTOR, *this, rhs ); }
+
+        TraceCAD & operator=( const TraceCAD & rhs )
+        { traceCAD( ASSIGN, *this, rhs ); return *this; }
+
+        virtual ~TraceCAD()
+        { traceCAD( DTOR, *this, *this ); }
+
+        void _PING() const
+        { traceCAD( PING, *this, *this ); }
+      };
+
+    template<class _Tp>
+      void traceCAD( TraceCADBase::What what_r,
+                     const TraceCAD<_Tp> & self_r,
+                     const TraceCAD<_Tp> & rhs_r )
+      {
+        switch( what_r )
+          {
+          case TraceCADBase::CTOR:
+          case TraceCADBase::DTOR:
+          case TraceCADBase::PING:
+            INT << self_r << what_r << std::endl;
+            break;
+          case TraceCADBase::COPYCTOR:
+          case TraceCADBase::ASSIGN:
+            INT << self_r << what_r << "( " << rhs_r << ")" << std::endl;
+            break;
+          }
+      }
+
+    /////////////////////////////////////////////////////////////////
+  } // namespace debug
+  ///////////////////////////////////////////////////////////////////
+  /////////////////////////////////////////////////////////////////
+} // namespace zypp
+///////////////////////////////////////////////////////////////////
+#endif // ZYPP_BASE_DEBUG_H
index afd294f..56f01dd 100644 (file)
@@ -6,6 +6,7 @@ SUBDIRS =
 ## ##################################################
 
 include_HEADERS =      \
+       Debug.h         \
        KindOf.h        \
        Logger.h        \
        Exception.h     \
index daf20f5..f3f015d 100644 (file)
@@ -50,7 +50,7 @@ namespace zypp
     /** */
     using boost::weak_ptr;
 
-    /** Use boost::intrusive_ptr as Ptr type*/
+    /** Use boost::intrusive_ptr as Ptr type */
     using boost::intrusive_ptr;
 
     using boost::static_pointer_cast;
@@ -72,10 +72,12 @@ namespace zypp
      *
      * Forwarding access from an interface to an implemantation class, an
      * RW_pointer prevents const interface methods from accidentally calling
-     * nonconst implementation methods. In case you have to do so, call
-     * unconst to get the <tt>_D *</tt>.
+     * nonconst implementation methods.
      *
      * The second template argument defaults to <tt>_Ptr = shared_ptr<_D></tt>.
+     *
+     * \see zypp::RWCOW_pointer for 'copy on write' functionality.
+     *
      * \code
      * #include "zypp/base/PtrTypes.h"
      *
@@ -92,7 +94,6 @@ namespace zypp
      *     void baa() const { _pimpl->... } // is Impl const *
      * };
      * \endcode
-     * \todo refine ctor and assign.
     */
     template<class _D, class _Ptr = shared_ptr<_D> >
       struct RW_pointer
@@ -109,17 +110,40 @@ namespace zypp
         : _dptr( dptr )
         {}
 
-        _D & operator*() { return *_dptr; }
-        const _D & operator*() const { return *_dptr; };
-        _D * operator->() { return _dptr.get(); }
-        const _D * operator->() const { return _dptr.get(); }
-        _D * get() { return _dptr.get(); }
-        const _D * get() const { return _dptr.get(); }
+        void reset()
+        { _dptr.reset(); }
+
+        void reset( typename _Ptr::element_type * dptr )
+        { _dptr.reset( dptr ); }
+
+        void swap( RW_pointer & rhs )
+        { _dptr.swap( rhs._dptr ); }
+
+        void swap( _Ptr & rhs )
+        { _dptr.swap( rhs ); }
+
+        const _D & operator*() const
+        { return *_dptr; };
+
+        const _D * operator->() const
+        { return _dptr.get(); }
 
-        _D * unconst() const { return _dptr.get(); }
+        const _D * get() const
+        { return _dptr.get(); }
 
+        _D & operator*()
+        { return *_dptr; }
+
+        _D * operator->()
+        { return _dptr.get(); }
+
+        _D * get()
+        { return _dptr.get(); }
+
+      private:
         _Ptr _dptr;
       };
+    ///////////////////////////////////////////////////////////////////
 
     /** \relates RW_pointer Stream output.
      *
@@ -136,38 +160,121 @@ namespace zypp
       }
 
     ///////////////////////////////////////////////////////////////////
-    /** Wrapper for \c const correct access via pointer.
+
+    ///////////////////////////////////////////////////////////////////
+    //
+    // CLASS NAME : RWCOW_pointer
+    //
+    /** \ref RW_pointer supporting 'copy on write' functionality.
      *
-     * Template specialization of RW_pointer, storing a raw <tt>_P *</tt>,
-     * which must be convertible into a <tt>_D *</tt>.
+     * \em Write access to the underlying object creates a copy, iff
+     * the object is shared.
      *
-     * \note The object pointed to will \b not be deleted. If you need
-     * automatic cleanup, use a \ref ZYPP_SMART_PTR instead of a
-     * raw pointer.
+     * See \ref RW_pointer.
     */
-    template<class _D,class _P>
-      struct RW_pointer<_D,_P*>
+    template<class _D, class _Ptr = shared_ptr<_D> >
+      struct RWCOW_pointer
       {
         typedef _D element_type;
+        typedef typename _Ptr::unspecified_bool_type unspecified_bool_type;
+
+        explicit
+        RWCOW_pointer( typename _Ptr::element_type * dptr = 0 )
+        : _dptr( dptr )
+        {}
 
         explicit
-        RW_pointer( _P * dptr = 0 )
+        RWCOW_pointer( _Ptr dptr )
         : _dptr( dptr )
         {}
 
-        _D & operator*() { return *_dptr; }
-        const _D & operator*() const { return *_dptr; };
-        _D * operator->() { return _dptr; }
-        const _D * operator->() const { return _dptr; }
-        _D * get() { return _dptr; }
-        const _D * get() const { return _dptr; }
+        void reset()
+        { _dptr.reset(); }
+
+        void reset( typename _Ptr::element_type * dptr )
+        { _dptr.reset( dptr ); }
+
+        void swap( RWCOW_pointer & rhs )
+        { _dptr.swap( rhs._dptr ); }
+
+        void swap( _Ptr & rhs )
+        { _dptr.swap( rhs ); }
+
+        operator unspecified_bool_type() const
+        { return _dptr; }
+
+        const _D & operator*() const
+        { return *_dptr; };
+
+        const _D * operator->() const
+        { return _dptr.get(); }
 
-        _D * unconst() const { return _dptr; }
+        const _D * get() const
+        { return _dptr.get(); }
 
-        _P * _dptr;
+        _D & operator*()
+        { assertUnshared(); return *_dptr; }
+
+        _D * operator->()
+        { assertUnshared(); return _dptr.get(); }
+
+        _D * get()
+        { assertUnshared(); return _dptr.get(); }
+
+      private:
+
+        void assertUnshared()
+        {
+          if ( rwcowIsShared( _dptr ) )
+            {
+              _dptr.reset( rwcowClone( _dptr.get() ) );
+            }
+        }
+
+      private:
+        _Ptr _dptr;
       };
+    ///////////////////////////////////////////////////////////////////
+
+    /** \relates RWCOW_pointer Check whether pointer is shared. */
+    template<class _D>
+      inline bool rwcowIsShared( const shared_ptr<_D> & ptr_r )
+      { return ptr_r.use_count() > 1; }
+
+    /** \relates RWCOW_pointer Check whether pointer is shared.
+     * \todo Quite zypp specific assumption that intrusive_ptr
+     * is derived from zypp::base::ReferenceCounted.
+    */
+    template<class _D>
+      inline bool rwcowIsShared( const intrusive_ptr<_D> & ptr_r )
+      { return ptr_r && (ptr_r->refCount() > 1); }
+
+    /** \relates RWCOW_pointer Clone the underlying object.
+     * Calls \a rhs <tt>-\>clone()</tt>. Being defined as a
+     * function outside \ref RWCOW_pointer allows to overload
+     * it, in case a specific \a _D does not have <tt>clone()</tt>.
+    */
+    template<class _D>
+      inline _D * rwcowClone( const _D * rhs )
+      { return rhs->clone(); }
+
+    ///////////////////////////////////////////////////////////////////
 
-    /////////////////////////////////////////////////////////////////
+    /** \relates RWCOW_pointer Stream output.
+     *
+     * Print the \c _D object the RWCOW_pointer refers, or \c "NULL"
+     * if the pointer is \c NULL.
+    */
+    template<class _D, class _Ptr>
+      inline std::ostream &
+      operator<<( std::ostream & str, const RWCOW_pointer<_D, _Ptr> & obj )
+      {
+        if ( obj.get() )
+          return str << *obj.get();
+        return str << std::string("NULL");
+      }
+
+    ///////////////////////////////////////////////////////////////////
 
     /*@}*/
 
index bf3e880..bd58b66 100644 (file)
@@ -63,7 +63,7 @@ namespace zypp
       { return *this; }
 
     public:
-      /** Reurn reference counter value. */
+      /** Return reference counter value. */
       unsigned refCount() const
       { return _counter; }