- Updated doc for callback receiver.
[platform/upstream/libzypp.git] / zypp / Callback.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/Callback.h
10  *
11 */
12 #ifndef ZYPP_CALLBACK_H
13 #define ZYPP_CALLBACK_H
14
15 #include "zypp/base/NonCopyable.h"
16
17 ///////////////////////////////////////////////////////////////////
18 namespace zypp
19 { /////////////////////////////////////////////////////////////////
20
21   /** \todo Eliminate this! */
22   namespace HACK {
23     class Callback
24     {
25     };
26   } // namespace HACK
27
28   ///////////////////////////////////////////////////////////////////
29   /** Callbacks light.
30    *
31    * \par The task report structure (SENDER SIDE).
32    *
33    * A default constructible struct derived from callback::ReportBase.
34    * It \b must \b not conatin any data, just virtual methods.
35    *
36    * These are the functions the sender invokes, and which will be forwarded
37    * to some receiver. If no receiver is present, the defined default
38    * implementations are invoked.
39    *
40    * For methods returning non-void, define a reasonable return value,
41    * because this is what you get back in case no receiver is listening.
42    *
43    * That way the sending side does not need to know whether some receiver
44    * is listening. And it enables the receiver to return a reasonable value,
45    * in case he's got no idea, what to else to return.
46    *
47    * \code
48    *   struct Foo : public callback::ReportBase
49    *   {
50    *     virtual void ping( int i )
51    *     {}
52    *     virtual int pong()
53    *     { return -1; }
54    *
55    *   };
56    * \endcode
57    *
58    * \par Sending a Task report (SENDER SIDE).
59    *
60    * Simply create a callback::SendReport<_Report>, where _Report
61    * is your task report structure. Invoke the callback functions
62    * as needed. That's it.
63    *
64    * \note Even creation and destruction of a callback::SendReport
65    * are indicated to a receiver. So even in case of an Exception,
66    * the receiver is able to recognize, that the task ended.
67    * So don't create it without need.
68    *
69    * \code
70    * {
71    *   callback::SendReport<Foo> report;
72    *   report->ping( 13 );
73    *   int response = report->pong();
74    * }
75    * \endcode
76    *
77    * \par Receiving Task reports (RECEIVER SIDE).
78    *
79    * To receive task reports of type \c Foo the recipient class
80    * derives from callback::ReceiveReport\<Foo\>. callback::ReceiveReport
81    * inherits \c Foo and provides two additional methods:
82    *
83    * \code
84    *   virtual void reportbegin() {}
85    *   virtual void reportend() {}
86    * \endcode
87    *
88    * These two are automatically invoked, whenever the sender
89    * creates a callback::SendReport instance, and when it gets
90    * destructed. So even if the sending task is aborted without
91    * sending an explicit notification, the reciever may notice it,
92    * by overloading \c reportend.
93    *
94    * Overload the methods you're interested in.
95    *
96    * \note In case you must return some value and don't know which,
97    * return the task structures default. The author of the task
98    * structure had to provide this value, so it's probabely better
99    * than anything you \e invent.
100    * \code
101    *   int somefunktion()
102    *   {
103    *     ...// don't know what to return?
104    *     return Foo::somefunktion();
105    *   }
106    * \endcode
107    *
108   */
109   namespace callback
110   { /////////////////////////////////////////////////////////////////
111
112     /**  */
113     struct ReportBase
114     {
115       virtual ~ReportBase()
116       {}
117     };
118
119     /**  */
120     template<class _Report>
121       class DistributeReport;
122
123     /**  */
124     template<class _Report>
125       struct ReceiveReport : public _Report
126       {
127         typedef DistributeReport<_Report> Distributor;
128
129         virtual void reportbegin()
130         {}
131         virtual void reportend()
132         {}
133       };
134
135     /**  */
136     template<class _Report>
137       struct DistributeReport
138       {
139        public:
140          typedef ReceiveReport<_Report> Receiver;
141
142          static DistributeReport & instance()
143          {
144            static DistributeReport _self;
145            return _self;
146          }
147
148          void setReceiver( Receiver & _rec )
149          { _receiver = &_rec; }
150
151          void noReceiver()
152          { _receiver = &_noReceiver; }
153
154       public:
155          Receiver * operator->()
156          { return _receiver; }
157
158       private:
159         DistributeReport()
160         : _receiver( &_noReceiver )
161         {}
162         Receiver _noReceiver;
163         Receiver * _receiver;
164       };
165
166     /**  */
167     template<class _Report>
168       struct SendReport : private zypp::base::NonCopyable
169       {
170         typedef DistributeReport<_Report> Distributor;
171
172         SendReport()
173         { Distributor::instance()->reportbegin(); }
174
175         ~SendReport()
176         { Distributor::instance()->reportend(); }
177
178         Distributor & operator->()
179         { return Distributor::instance(); }
180       };
181
182     /////////////////////////////////////////////////////////////////
183   } // namespace callback
184   ///////////////////////////////////////////////////////////////////
185   /////////////////////////////////////////////////////////////////
186 } // namespace zypp
187 ///////////////////////////////////////////////////////////////////
188 #endif // ZYPP_CALLBACK_H