1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \----------------------------------------------------------------------/
10 * This file contains private API, this might break at any time between releases.
11 * You have been warned!
14 #ifndef ZYPP_BASE_EVENTDISPATCHER_DEFINED
15 #define ZYPP_BASE_EVENTDISPATCHER_DEFINED
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>
28 class EventDispatcher;
31 class EventDispatcherPrivate;
34 * The EventDispatcher class implements the libzypp event loop.
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.
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.
49 class LIBZYPP_NG_EXPORT EventDispatcher : public Base
51 ZYPP_DECLARE_PRIVATE(EventDispatcher)
52 friend class AbstractEventSource;
57 using Ptr = std::shared_ptr<EventDispatcher>;
58 using WeakPtr = std::shared_ptr<EventDispatcher>;
59 using IdleFunction = std::function<bool ()>;
62 * Creates a new EventDispatcher, use this function to create a Dispatcher
63 * running on the default thread
65 * \note the glib implementation will use the g_default_context(), this means
66 * it will attach to any running main loop
68 static std::shared_ptr<EventDispatcher> createMain ( );
71 * Creates a new EventDispatcher, use this function to create a Dispatcher
72 * running on a threads aside the main thread
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
78 static std::shared_ptr<EventDispatcher> createForThread ( );
80 virtual ~EventDispatcher();
83 * Enters the eventloop once and dequeues all pending events, once the event queue is empty the
86 virtual bool run_once();
89 * Start dispatching events, this function will block until \sa quit was called for the EventDispatcher instance
94 * Stop dispatching events and return from the main loop.
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
102 template< typename T = IdleFunction >
103 static void invokeOnIdle ( T &&callback )
105 auto ev = instance();
107 ev->invokeOnIdleImpl( std::forward<T>(callback) );
111 * Schedules a \sa std::shared_ptr to be unreferenced in the next idle phase of the
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.
117 template< typename T >
118 static void unrefLater ( T &&ptr ) {
119 auto ev = instance();
121 ev->unrefLaterImpl( std::static_pointer_cast<void>( std::forward<T>(ptr) ) );
125 * Returns the number of the currently active timers
127 ulong runningTimers() const;
130 * Returns the EventDispatcher instance for the current thread.
132 static std::shared_ptr<EventDispatcher> instance();
137 * Create a new instance of the EventDispatcher, if \a ctx is given it is used as the new
138 * context for the eventloop
140 EventDispatcher( void *ctx = nullptr );
145 void unrefLaterImpl ( std::shared_ptr<void> &&ptr );
150 void invokeOnIdleImpl ( IdleFunction &&callback );
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
158 virtual void updateEventSource ( AbstractEventSource *notifier, int fd, int mode );
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
166 virtual void removeEventSource ( AbstractEventSource *notifier, int fd = -1 );
169 * Adds a new Timer instance to the internal timer list
171 virtual void registerTimer ( Timer *timer );
174 * Removes a timer from the internal timer list, once a Timer is removed it does not fire anymore
176 virtual void removeTimer ( Timer *timer );