9#include <zypp-core/zyppng/base/UnixSignalSource>
14 return ( G_IO_IN | G_IO_HUP );
41 if ( ( rEvents & requestedEvs ) != 0 ) {
48 if ( ( rEvents & G_IO_ERR) && ( requestedEvs & G_IO_ERR ) )
66 (void)
new (&src->
pollfds) std::vector<GUnixPollFD>();
77 g_source_remove_unix_fd( &src->
source, fd.
tag );
81 src->
pollfds.std::vector< GUnixPollFD >::~vector();
82 g_source_destroy( &src->
source );
83 g_source_unref( &src->
source );
101 bool hasPending =
false;
103 for (
auto fdIt = src->
pollfds.begin(); fdIt != src->
pollfds.end(); ) {
104 if ( fdIt->tag ==
nullptr ) {
108 fdIt = src->
pollfds.erase( fdIt );
110 GIOCondition pendEvents = g_source_query_unix_fd(
source, fdIt->tag );
111 if ( pendEvents & G_IO_NVAL ){
113 fdIt = src->
pollfds.erase( fdIt );
115 hasPending = hasPending || ( pendEvents & fdIt->reqEvents );
122 return hasPending || src->
pollfds.empty();
131 return G_SOURCE_REMOVE;
141 return G_SOURCE_REMOVE;
147 if ( pollfd.
tag !=
nullptr ) {
148 GIOCondition pendEvents = g_source_query_unix_fd(
source, pollfd.
tag );
150 if ( (pendEvents & pollfd.
reqEvents ) != 0 ) {
160 return G_SOURCE_CONTINUE;
182 uint64_t nextTimeout =
source->_t->remaining();
185 if ( nextTimeout > G_MAXINT )
188 *timeout =
static_cast<gint
>( nextTimeout );
190 return ( nextTimeout == 0 );
206 if (
source->_t ==
nullptr )
224 g_source_destroy( &src->
source );
225 g_source_unref( &src->
source );
235 if( dPtr->runIdleTasks() ) {
236 return G_SOURCE_CONTINUE;
239 g_source_unref ( dPtr->_idleSource );
240 dPtr->_idleSource =
nullptr;
242 return G_SOURCE_REMOVE;
247 source = g_child_watch_source_new( pid );
253 ,
callback( std::move( other.callback ) )
255 other.source =
nullptr;
261 g_source_destroy(
source );
270 callback = std::move( other.callback );
271 other.source =
nullptr;
283 g_main_context_ref (
_ctx );
285 _ctx = g_main_context_new();
294 GLibTimerSource::destruct( src );
297 GAbstractEventSource::destruct( src );
308 g_main_context_unref(
_ctx );
318 while ( runQueue.size() ) {
351 auto data = std::move( that->
_waitPIDs.at(pid) );
355 data.callback( pid, status );
357 g_spawn_close_pid( pid );
361 }
catch (
const std::out_of_range &e ) {
386 auto &evSrcList = d->_eventSources;
387 auto itToEvSrc = std::find_if( evSrcList.begin(), evSrcList.end(), [ notifyPtr ](
const auto elem ){ return elem->eventSource == notifyPtr; } );
388 if ( itToEvSrc == evSrcList.end() ) {
392 evSrcList.push_back( evSrc );
394 g_source_attach( &evSrc->
source, d->_ctx );
397 evSrc = (*itToEvSrc);
400 auto it = std::find_if( evSrc->
pollfds.begin(), evSrc->
pollfds.end(), [fd](
const auto &currPollFd ) {
401 return currPollFd.pollfd == fd;
404 if ( it != evSrc->
pollfds.end() ) {
406 it->reqEvents =
static_cast<GIOCondition
>( cond );
407 g_source_modify_unix_fd( &evSrc->
source, it->tag,
static_cast<GIOCondition
>(cond) );
411 static_cast<GIOCondition
>(cond),
413 g_source_add_unix_fd( &evSrc->
source, fd,
static_cast<GIOCondition
>(cond) )
428 auto &evList = d->_eventSources;
429 auto it = std::find_if( evList.begin(), evList.end(), [ ptr ](
const auto elem ){ return elem->eventSource == ptr; } );
431 if ( it == evList.end() )
434 auto &fdList = (*it)->pollfds;
440 for (
auto &pFD : fdList ) {
442 g_source_remove_unix_fd( &(*it)->source, pFD.tag );
447 auto fdIt = std::find_if( fdList.begin(), fdList.end(), [ fd ](
const auto &pFd ){ return pFd.pollfd == fd; } );
448 if ( fdIt != fdList.end() ) {
450 g_source_remove_unix_fd( &(*it)->source, (*fdIt).tag );
463 if ( t->
_t == &timer )
469 d->_runningTimers.push_back( newSrc );
471 g_source_attach( &newSrc->
source, d->_ctx );
477 auto it = std::find_if( d->_runningTimers.begin(), d->_runningTimers.end(), [ &timer ](
const GLibTimerSource *src ){
478 return src->_t == &timer;
481 if ( it != d->_runningTimers.end() ) {
483 d->_runningTimers.erase( it );
490 return d_func()->_ctx;
499 bool eventTriggered =
false;
501 while ( !eventTriggered ) {
502 g_timer_start( *timer );
503 const int res =
eintrSafeCall( g_poll, &pollFd, 1, timeout );
513 timeout -= g_timer_elapsed( *timer,
nullptr );
514 if ( timeout < 0 ) timeout = 0;
518 ERR <<
"g_poll error: " <<
strerror(errno) << std::endl;
522 eventTriggered =
true;
538 data.
tag = g_source_attach ( data.
source, d->_ctx );
539 d->_waitPIDs.insert( std::make_pair( pid, std::move(data) ) );
546 d->_waitPIDs.erase( pid );
547 }
catch (
const std::out_of_range &e ) {
557 UnixSignalSourceRef r;
558 if ( d->_signalSource.expired ()) {
561 r = d->_signalSource.lock ();
568 return g_main_context_iteration( d_func()->_ctx,
false );
574 d->_idleFuncs.push( std::move(
callback) );
575 d->enableIdleSource();
581 d->_unrefLater.push_back( std::move(ptr) );
582 d->enableIdleSource();
587 d_func()->_unrefLater.clear();
592 return d_func()->_runningTimers.size();
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Base class for Exception.
std::weak_ptr< EventDispatcher > eventDispatcher() const
virtual void onFdReady(int fd, int events)=0
std::shared_ptr< T > shared_this() const
std::unique_ptr< BasePrivate > d_ptr
~EventDispatcherPrivate() override
std::queue< EventDispatcher::IdleFunction > _idleFuncs
std::vector< std::shared_ptr< void > > _unrefLater
static void waitPidCallback(GPid pid, gint status, gpointer user_data)
std::thread::id _myThreadId
std::unordered_map< int, GlibWaitPIDData > _waitPIDs
std::vector< GAbstractEventSource * > _eventSources
std::vector< GLibTimerSource * > _runningTimers
EventDispatcherPrivate(GMainContext *ctx, EventDispatcher &p)
static std::shared_ptr< EventDispatcher > create()
~EventDispatcher() override
friend class AbstractEventSource
UnixSignalSourceRef unixSignalSource()
virtual void registerTimer(Timer &timer)
void clearUnrefLaterList()
ulong runningTimers() const
void unrefLaterImpl(std::shared_ptr< void > &&ptr)
void * nativeDispatcherHandle() const
Returns the native dispatcher handle if the used implementation supports it.
std::function< bool()> IdleFunction
EventDispatcher(void *ctx=nullptr)
static bool waitForFdEvent(const int fd, int events, int &revents, int &timeout)
virtual void removeTimer(Timer &timer)
void trackChildProcess(int pid, std::function< void(int, int)> callback)
bool untrackChildProcess(int pid)
virtual void updateEventSource(AbstractEventSource ¬ifier, int fd, int mode)
virtual void removeEventSource(AbstractEventSource ¬ifier, int fd=-1)
static void setThreadDispatcher(const std::shared_ptr< EventDispatcher > &disp)
static std::shared_ptr< EventDispatcher > instance()
void invokeOnIdleImpl(IdleFunction &&callback)
The Timer class provides repetitive and single-shot timers.
static UnixSignalSourceRef create()
static gboolean eventLoopIdleFunc(gpointer user_data)
Called when the event loop is idle, here we run cleanup tasks and call later() callbacks of the user.
static GSourceFuncs glibTimerSourceFuncs
static int gioConditionToEventTypes(const GIOCondition rEvents, const int requestedEvs)
std::string strerror(int errno_r) ZYPP_API
Return string describing the error_r code.
auto eintrSafeCall(Fun &&function, Args &&... args)
static int evModeToMask(int mode)
static GSourceFuncs abstractEventSourceFuncs
static gboolean check(GSource *source)
std::vector< GUnixPollFD > pollfds
AbstractEventSource * eventSource
static gboolean dispatch(GSource *source, GSourceFunc, gpointer)
static GAbstractEventSource * create(EventDispatcherPrivate *ev)
static void destruct(GAbstractEventSource *src)
static gboolean prepare(GSource *, gint *timeout)
EventDispatcherPrivate * _ev
static void destruct(GLibTimerSource *src)
static gboolean prepare(GSource *src, gint *timeout)
static gboolean check(GSource *source)
static GLibTimerSource * create()
static gboolean dispatch(GSource *source, GSourceFunc, gpointer)
GlibWaitPIDData & operator=(GlibWaitPIDData &&other) noexcept
EventDispatcher::WaitPidCallback callback
GlibWaitPIDData(GPid pid)
std::shared_ptr< EventDispatcher > dispatcher()
static ZYPP_API ThreadData & current()
void setDispatcher(const std::shared_ptr< EventDispatcher > &disp)
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
#define ZYPP_IMPL_PRIVATE(Class)