add asSting overload for string&&
[platform/upstream/libzypp.git] / zypp / base / ReferenceCounted.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/base/ReferenceCounted.h
10  *
11 */
12 #ifndef ZYPP_BASE_REFERENCECOUNTED_H
13 #define ZYPP_BASE_REFERENCECOUNTED_H
14
15 #include <iosfwd>
16
17 #include "zypp/base/PtrTypes.h"
18
19 ///////////////////////////////////////////////////////////////////
20 namespace zypp
21 { /////////////////////////////////////////////////////////////////
22   ///////////////////////////////////////////////////////////////////
23   namespace base
24   { /////////////////////////////////////////////////////////////////
25
26     ///////////////////////////////////////////////////////////////////
27     //
28     //  CLASS NAME : ReferenceCounted
29     //
30     /** Base class for reference counted objects.
31      * \todo Make counter thread safe.
32     */
33     class ReferenceCounted
34     {
35       /** Stream output via dumpOn. */
36       friend std::ostream & operator<<( std::ostream & str, const ReferenceCounted & obj );
37
38     public:
39       /** Default ctor.
40        * Initial reference count is zero.
41       */
42       ReferenceCounted();
43
44       /** Copy ctor.
45        * Initial reference count is zero.
46       */
47       ReferenceCounted( const ReferenceCounted & rhs );
48
49       /** Dtor.
50        * \throw std::out_of_range if reference count is not zero.
51       */
52       virtual ~ReferenceCounted();
53
54       /** Assignment.
55        * Reference count remains untouched.
56       */
57       ReferenceCounted & operator=( const ReferenceCounted & )
58       { return *this; }
59
60     public:
61       /** Return reference counter value. */
62       unsigned refCount() const
63       { return _counter; }
64
65       /** Add a reference. */
66       void ref() const
67       { ref_to( ++_counter ); }
68
69       /** Release a reference.
70        * Deletes the object if reference count gets zero.
71        * \throw std::out_of_range if reference count is zero.
72       */
73       void unref() const
74       {
75         if ( !_counter )
76           unrefException(); // will throw!
77         if ( --_counter )
78           unref_to( _counter );
79         else
80           delete this;
81       }
82
83       /** Called by zypp::intrusive_ptr to add a reference.
84        * \see ZYPP_SMART_PTR
85       */
86       static void add_ref( const ReferenceCounted * ptr_r )
87       { if( ptr_r ) ptr_r->ref(); }
88
89       /** Called by zypp::intrusive_ptr to add a reference.
90        * \see ZYPP_SMART_PTR
91       */
92       static void release( const ReferenceCounted * ptr_r )
93       { if( ptr_r ) ptr_r->unref(); }
94
95     protected:
96       /** Overload to realize std::ostream & operator\<\<. */
97       virtual std::ostream & dumpOn( std::ostream & str ) const;
98
99       /** Trigger derived classes after refCount was increased. */
100       virtual void ref_to( unsigned /* rep_cnt_r */ ) const {}
101
102       /** Trigger derived classes after refCount was decreased.
103        * No trigger is sent, if refCount got zero (i.e. the
104        * object is deleted).
105        **/
106       virtual void unref_to( unsigned /* rep_cnt_r */ ) const {}
107
108     private:
109       /** The reference counter. */
110       mutable unsigned _counter;
111
112       /** Throws Exception on unref. */
113       void unrefException() const;
114     };
115     ///////////////////////////////////////////////////////////////////
116
117     /** \relates ReferenceCounted intrusive_ptr hook to add_ref. */
118     inline void intrusive_ptr_add_ref( const ReferenceCounted * ptr_r )
119     { ReferenceCounted::add_ref( ptr_r ); }
120
121     /** \relates ReferenceCounted intrusive_ptr hook to release. */
122     inline void intrusive_ptr_release( const ReferenceCounted * ptr_r )
123     { ReferenceCounted::release( ptr_r ); }
124
125     /** \relates ReferenceCounted Stream output. */
126     inline std::ostream & operator<<( std::ostream & str, const ReferenceCounted & obj )
127     { return obj.dumpOn( str ); }
128
129     /////////////////////////////////////////////////////////////////
130   } // namespace base
131   ///////////////////////////////////////////////////////////////////
132   /////////////////////////////////////////////////////////////////
133 } // namespace zypp
134 ///////////////////////////////////////////////////////////////////
135
136 #define IMPL_PTR_TYPE(NAME) \
137 void intrusive_ptr_add_ref( const NAME * ptr_r )               \
138 { zypp::base::ReferenceCounted::add_ref( ptr_r ); }                  \
139 void intrusive_ptr_release( const NAME * ptr_r )               \
140 { zypp::base::ReferenceCounted::release( ptr_r ); }
141
142 ///////////////////////////////////////////////////////////////////
143 #endif // ZYPP_BASE_REFERENCECOUNTED_H