Imported Upstream version 17.22.1
[platform/upstream/libzypp.git] / zypp / zyppng / base / eventdispatcher.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \----------------------------------------------------------------------/
9 *
10 * This file contains private API, this might break at any time between releases.
11 * You have been warned!
12 *
13 */
14 #ifndef ZYPP_BASE_EVENTDISPATCHER_DEFINED
15 #define ZYPP_BASE_EVENTDISPATCHER_DEFINED
16
17 #include <zypp/zyppng/base/zyppglobal.h>
18 #include <zypp/zyppng/base/Signals>
19 #include <zypp/zyppng/base/Base>
20 #include <zypp/zyppng/base/AbstractEventSource>
21 #include <memory>
22 #include <functional>
23
24 namespace zyppng {
25
26 class SocketNotifier;
27 class Timer;
28 class EventDispatcher;
29
30
31 class EventDispatcherPrivate;
32
33 /*!
34  * The EventDispatcher class implements the libzypp event loop.
35  *
36  * A event loop is used to execute multiple tasks concurrently. This is not implemented using threads but usually by either
37  * using Timers to poll a ressource or by reacting on events from a file descriptor or socket.
38  * In a application like zypper where we heavily make use of I/O heavy tasks like downloading packages, rebuilding the repo metadata
39  * or generating a checksum over a file the application needs to wait more for those tasks to finish than actually doing anything.
40  * By using a event loop we can start one of those tasks and let the OS handle the execution and subscribe to certain events that can happen,
41  * utilizing more of the CPU compared to starting all the tasks serially.
42  *
43  * Libzypp is using a thread local eventloop, means each thread needs to start its own loop. Only special case is when
44  * we need to work together with a already exisiting event loop, for example in a Qt application. The default implementation however
45  * uses the glib eventloop, just like Qt and GTK, so integrating libzypp here is just a matter of passing the default main context
46  * to the constructor of \a EventDispatcher.
47  *
48  */
49 class LIBZYPP_NG_EXPORT EventDispatcher : public Base
50 {
51   ZYPP_DECLARE_PRIVATE(EventDispatcher)
52   friend class AbstractEventSource;
53   friend class Timer;
54
55 public:
56
57   using Ptr = std::shared_ptr<EventDispatcher>;
58   using WeakPtr = std::shared_ptr<EventDispatcher>;
59   using IdleFunction = std::function<bool ()>;
60
61   /*!
62    * Creates a new EventDispatcher, use this function to create a Dispatcher
63    * running on the default thread
64    *
65    * \note the glib implementation will use the g_default_context(), this means
66    * it will attach to any running main loop
67    */
68   static std::shared_ptr<EventDispatcher> createMain ( );
69
70   /*!
71    * Creates a new EventDispatcher, use this function to create a Dispatcher
72    * running on a threads aside the main thread
73    *
74    * \note the glib implementation will use the g_main_context_get_thread_default(), this means
75    * it will attach to any loop that was set as the default for the current thread, if there is no
76    * default context a new one will be created
77    */
78   static std::shared_ptr<EventDispatcher> createForThread ( );
79
80   virtual ~EventDispatcher();
81
82   /*!
83    * Enters the eventloop once and dequeues all pending events, once the event queue is empty the
84    * function returns
85    */
86   virtual bool run_once();
87
88   /*!
89    * Start dispatching events, this function will block until \sa quit was called for the EventDispatcher instance
90    */
91   virtual void run ();
92
93   /*!
94    * Stop dispatching events and return from the main loop.
95    */
96   virtual void quit ();
97
98   /*!
99    * \brief Convenience function to schedule a callback to be called later.
100    * \param callback a std::function that is called after all other events have been processed
101    */
102   template< typename T = IdleFunction >
103   static void invokeOnIdle ( T &&callback )
104   {
105     auto ev = instance();
106     if ( ev )
107       ev->invokeOnIdleImpl( std::forward<T>(callback) );
108   }
109
110   /*!
111    * Schedules a \sa std::shared_ptr to be unreferenced in the next idle phase of the
112    * event loop.
113    *
114    * In some cases it might be required to delay the cleanup of a ressource until the current
115    * event loop iteration was finished, in case there are more pending events for the ressource.
116    */
117   template< typename T >
118   static void unrefLater ( T &&ptr ) {
119     auto ev = instance();
120     if ( ev )
121       ev->unrefLaterImpl( std::static_pointer_cast<void>( std::forward<T>(ptr) ) );
122   }
123
124   /*!
125    * Returns the number of the currently active timers
126    */
127   ulong runningTimers() const;
128
129   /*!
130    * Returns the EventDispatcher instance for the current thread.
131    */
132   static std::shared_ptr<EventDispatcher> instance();
133
134 protected:
135
136   /*!
137    * Create a new instance of the EventDispatcher, if \a ctx is given it is used as the new
138    * context for the eventloop
139    */
140   EventDispatcher( void *ctx = nullptr );
141
142   /*!
143    * \see unrefLater
144    */
145   void unrefLaterImpl ( std::shared_ptr<void> &&ptr );
146
147   /*!
148    * \see invokeOnIdle
149    */
150   void invokeOnIdleImpl ( IdleFunction &&callback );
151
152   /*!
153    * Updates or registeres a event source in the event loop
154    * \param notifier The event source implementation that should receive the event notification
155    * \param fd The file descriptor that is added to the internal watchlist
156    * \param mode The watch mode for the given file desriptor \sa zyppng::AbstractEventSource::EventTypes
157    */
158   virtual void updateEventSource ( AbstractEventSource *notifier, int fd, int mode );
159
160   /*!
161    * Removes a file descriptor from the internal watchlist, if \a fd is set to -1 all file descriptors
162    * associated with the \sa AbstractEventSource are removed
163    * \param notifier The \sa AbstractEventSource parent of the file descriptor
164    * \param fd The file descriptor to be removed, set to -1 to remove all descriptors for a \sa AbstractEventSource
165    */
166   virtual void removeEventSource   ( AbstractEventSource *notifier, int fd = -1 );
167
168   /*!
169    * Adds a new Timer instance to the internal timer list
170    */
171   virtual void registerTimer ( Timer *timer );
172
173   /*!
174    * Removes a timer from the internal timer list, once a Timer is removed it does not fire anymore
175    */
176   virtual void removeTimer ( Timer *timer );
177 };
178
179 }
180
181 #endif