38static_assert (
sizeof   (PollFD)               == 
sizeof   (
struct pollfd));
 
   39static_assert (offsetof (PollFD, fd)           == offsetof (
struct pollfd, fd));
 
   40static_assert (
sizeof (((PollFD*) 0)->fd)      == 
sizeof (((
struct pollfd*) 0)->fd));
 
   41static_assert (offsetof (PollFD, events)       == offsetof (
struct pollfd, events));
 
   42static_assert (
sizeof (((PollFD*) 0)->events)  == 
sizeof (((
struct pollfd*) 0)->events));
 
   43static_assert (offsetof (PollFD, revents)      == offsetof (
struct pollfd, revents));
 
   44static_assert (
sizeof (((PollFD*) 0)->revents) == 
sizeof (((
struct pollfd*) 0)->revents));
 
   47static volatile int global_id_counter = 65536;
 
   51  uint id = __sync_fetch_and_add (&global_id_counter, +1);
 
   53    fatal_error (
"EventLoop: id counter overflow, please report"); 
 
   71  template<
class D> 
void swap (D &a, D &b) { D t = a; a = b; b = t; }
 
   73  typedef Data* iterator;
 
   74  QuickArray (
uint n_reserved, Data *reserved) : data_ (reserved), n_elements_ (0), n_reserved_ (n_reserved), reserved_ (reserved) {}
 
   76  uint        size       ()
 const       { 
return n_elements_; }
 
   77  uint        capacity   ()
 const       { 
return std::max (n_elements_, n_reserved_); }
 
   78  bool        empty      ()
 const       { 
return n_elements_ == 0; }
 
   79  Data*       data       ()
 const       { 
return data_; }
 
   80  Data&       operator[] (
uint n)       { 
return data_[n]; }
 
   81  const Data& operator[] (
uint n)
 const { 
return data_[n]; }
 
   82  iterator    begin      ()             { 
return &data_[0]; }
 
   83  iterator    end        ()             { 
return &data_[n_elements_]; }
 
   84  void        shrink     (
uint n)       { n_elements_ = 
std::min (n_elements_, n); }
 
   87    swap (data_,       o.data_);
 
   88    swap (n_elements_, o.n_elements_);
 
   89    swap (n_reserved_, o.n_reserved_);
 
   90    swap (reserved_,   o.reserved_);
 
   92  void        push       (
const Data &d)
 
   94    const uint idx = n_elements_;
 
  106    const size_t sz = n * 
sizeof (Data);
 
  107    const bool migrate_reserved = 
UNLIKELY (data_ == reserved_);        
 
  108    Data *mem = (Data*) (migrate_reserved ? 
malloc (sz) : 
realloc (data_, sz));
 
  111    if (migrate_reserved)
 
  113        memcpy (mem, data_, n_elements_ * 
sizeof (Data));
 
 
  129EventLoop::EventLoop (
MainLoop &main) :
 
  130  main_loop_ (&main), dispatch_priority_ (0), primary_ (false)
 
  132  poll_sources_.reserve (7);
 
  137EventLoop::~EventLoop ()
 
  144EventLoop::find_first_L()
 
  146  static EventSourceP null_source;
 
  147  return sources_.
empty() ? null_source : sources_[0];
 
  151EventLoop::find_source_L (
uint id)
 
  153  for (SourceList::iterator lit = sources_.
begin(); lit != sources_.
end(); lit++)
 
  154    if (
id == (*lit)->id_)
 
  156  static EventSourceP null_source;
 
  161EventLoop::has_primary_L()
 
  165  for (SourceList::iterator lit = sources_.
begin(); lit != sources_.
end(); lit++)
 
  166    if ((*lit)->primary())
 
  175  return has_primary_L();
 
 
  179EventLoop::flag_primary (
bool on)
 
  182  const bool was_primary = primary_;
 
  184  if (primary_ != was_primary)
 
  195static const int16 UNDEFINED_PRIORITY = -32768;
 
  200  static_assert (UNDEFINED_PRIORITY < 1, 
"");
 
  204  source->loop_ = 
this;
 
  205  source->id_ = alloc_id();
 
  206  source->loop_state_ = WAITING;
 
  207  source->priority_ = priority;
 
 
  221  source->loop_ = NULL;
 
  222  source->loop_state_ = WAITING;
 
  223  auto pos = find (sources_.
begin(), sources_.
end(), source);
 
  225  sources_.
erase (pos);
 
  226  release_id (source->id_);
 
  241    remove_source_Lm (source);
 
 
  251  const bool removal = 
try_remove (*id_pointer);
 
 
  260    warning (
"%s: failed to remove loop source: %u", __func__, 
id);
 
 
  272  auto once_handler = [vfunc,once_id]() { *once_id = 0; vfunc(); };
 
  273  EventSourceP source = TimedSource::create (once_handler, delay_ms, 0);
 
  274  source->loop_ = 
this;
 
  275  source->id_ = alloc_id();
 
  276  source->loop_state_ = WAITING;
 
  277  source->priority_ = priority;
 
  284        remove_source_Lm (source);
 
  289    *once_id = source->id_;
 
  292    warning (
"%s: failed to remove loop source: %u", __func__, once_id);
 
 
  306EventLoop::kill_sources_Lm()
 
  313      remove_source_Lm (source);
 
  336  EventLoopP main_loop_guard = shared_ptr_cast<EventLoop*> (main_loop_);
 
  338  if (
this != main_loop_)
 
  339    main_loop_->kill_loop_Lm (*
this);
 
  341    main_loop_->kill_loops_Lm();
 
 
  349  main_loop_->wakeup_poll();
 
 
  353MainLoop::MainLoop() :
 
  355  rr_index_ (0), running_ (false), has_quit_ (false), quit_code_ (0), gcontext_ (NULL)
 
  358  const int err = eventfd_.open();
 
  360    fatal_error (
"MainLoop: failed to create wakeup pipe: %s", strerror (-err));
 
  387MainLoop::wakeup_poll()
 
  394MainLoop::add_loop_L (EventLoop &loop)
 
  397  loops_.push_back (shared_ptr_cast<EventLoop> (&loop));
 
  402MainLoop::kill_loop_Lm (EventLoop &loop)
 
  405  loop.kill_sources_Lm();
 
  408      loop.main_loop_ = NULL;
 
  410                                                           [&loop] (EventLoopP &lp) { return lp.get() == &loop; });
 
  418      if (it != loops_.end())
 
  425MainLoop::kill_loops_Lm()
 
  427  while (loops_.size() > 1 || loops_[0].get() != 
this)
 
  429      EventLoopP loop = loops_[0].get() != 
this ? loops_[0] : loops_[loops_.size() - 1];
 
  430      kill_loop_Lm (*loop);
 
  432  kill_loop_Lm (*
this);
 
  438  EventLoopP main_loop_guard = shared_ptr_cast<EventLoop> (
this);
 
  441  running_ = !has_quit_;
 
  443    iterate_loops_Lm (state, 
true, 
true);
 
  444  const int last_quit_code = quit_code_;
 
  448  return last_quit_code;
 
 
  462  quit_code_ = quit_code;
 
 
  469MainLoop::finishable_L()
 
  472  bool found_primary = primary_;
 
  473  for (
size_t i = 0; !found_primary && i < loops_.size(); i++)
 
  474    if (loops_[i]->has_primary_L())
 
  475      found_primary = 
true;
 
  476  return !found_primary; 
 
  483  return finishable_L();
 
 
  499  EventLoopP main_loop_guard = shared_ptr_cast<EventLoop> (
this);
 
  502  const bool was_running = running_;    
 
  504  const bool sources_pending = iterate_loops_Lm (state, may_block, 
true);
 
  505  running_ = was_running && !has_quit_;
 
  506  return sources_pending;
 
 
  512  EventLoopP main_loop_guard = shared_ptr_cast<EventLoop> (
this);
 
  515  const bool was_running = running_;    
 
  518    if (!iterate_loops_Lm (state, 
false, 
true))
 
  520  running_ = was_running && !has_quit_;
 
 
  528  EventLoopP main_loop_guard = shared_ptr_cast<EventLoop> (
this);
 
  529  return iterate_loops_Lm (state, 
false, 
false);
 
 
  537  if (glib_main_context)
 
  541      if (!g_main_context_acquire (glib_main_context))
 
  543      gcontext_ = g_main_context_ref (glib_main_context);
 
  547      glib_main_context = gcontext_;
 
  549      g_main_context_release (glib_main_context);
 
  550      g_main_context_unref (glib_main_context);
 
 
  562  GPollFD *gpfd = (GPollFD*) pfd;
 
  563  static_assert (
sizeof (GPollFD) == 
sizeof (
PollFD), 
"");
 
  564  static_assert (
sizeof (gpfd->fd) == 
sizeof (pfd->fd), 
"");
 
  565  static_assert (
sizeof (gpfd->events) == 
sizeof (pfd->events), 
"");
 
  566  static_assert (
sizeof (gpfd->revents) == 
sizeof (pfd->revents), 
"");
 
  567  static_assert (offsetof (GPollFD, fd) == offsetof (
PollFD, fd), 
"");
 
  568  static_assert (offsetof (GPollFD, events) == offsetof (
PollFD, events), 
"");
 
  569  static_assert (offsetof (GPollFD, revents) == offsetof (
PollFD, revents), 
"");
 
  585EventLoop::unpoll_sources_U() 
 
  592EventLoop::collect_sources_Lm (LoopState &state)
 
  603  if (
UNLIKELY (!state.seen_primary && primary_))
 
  604    state.seen_primary = 
true;
 
  605  EventSourceP* arraymem[7]; 
 
  606  QuickSourcePArray poll_candidates (
ARRAY_SIZE (arraymem), arraymem);
 
  608  dispatch_priority_ = UNDEFINED_PRIORITY; 
 
  609  for (SourceList::iterator lit = sources_.
begin(); lit != sources_.
end(); lit++)
 
  611      EventSource &source = **lit;
 
  612      if (
UNLIKELY (!state.seen_primary && source.primary_))
 
  613        state.seen_primary = 
true;
 
  614      if (source.loop_ != 
this ||                               
 
  615          (source.dispatching_ && !source.may_recurse_))        
 
  617      if (source.priority_ > dispatch_priority_ &&              
 
  618          source.loop_state_ == NEEDS_DISPATCH)                 
 
  619        dispatch_priority_ = source.priority_;                  
 
  620      if (source.priority_ > dispatch_priority_ ||              
 
  621          (source.priority_ == dispatch_priority_ &&            
 
  622           source.loop_state_ == NEEDS_DISPATCH))               
 
  623        poll_candidates.push (&*lit);                           
 
  627  for (
size_t i = 0; i < poll_candidates.size(); i++)
 
  628    if ((*poll_candidates[i])->priority_ > dispatch_priority_ || 
 
  629        ((*poll_candidates[i])->priority_ == dispatch_priority_ &&
 
  630         (*poll_candidates[i])->loop_state_ == NEEDS_DISPATCH)) 
 
  631      poll_sources_.
push_back (*poll_candidates[i]);
 
  639EventLoop::prepare_sources_Lm (LoopState &state, QuickPfdArray &pfda)
 
  643  for (
auto lit = poll_sources_.
begin(); lit != poll_sources_.
end(); lit++)
 
  645      EventSource &source = **lit;
 
  646      if (source.loop_ != 
this) 
 
  650      const bool need_dispatch = source.prepare (state, &timeout);
 
  652      if (source.loop_ != 
this)
 
  656          dispatch_priority_ = 
std::max (dispatch_priority_, source.priority_); 
 
  657          source.loop_state_ = NEEDS_DISPATCH;
 
  660      source.loop_state_ = PREPARED;
 
  662        state.timeout_usecs = 
std::min (state.timeout_usecs, timeout);
 
  663      uint npfds = source.n_pfds();
 
  664      for (
uint i = 0; i < npfds; i++)
 
  665        if (source.pfds_[i].pfd->fd >= 0)
 
  667            uint idx = pfda.size();
 
  668            source.pfds_[i].idx = idx;
 
  669            pfda.push (*source.pfds_[i].pfd);
 
  670            pfda[idx].revents = 0;
 
  673          source.pfds_[i].idx = 4294967295U; 
 
  675  return dispatch_priority_ > UNDEFINED_PRIORITY;
 
  679EventLoop::check_sources_Lm (LoopState &state, 
const QuickPfdArray &pfda)
 
  683  for (
auto lit = poll_sources_.
begin(); lit != poll_sources_.
end(); lit++)
 
  685      EventSource &source = **lit;
 
  686      if (source.loop_ != 
this && 
 
  687          source.loop_state_ != PREPARED)
 
  689      uint npfds = source.n_pfds();
 
  690      for (
uint i = 0; i < npfds; i++)
 
  692          uint idx = source.pfds_[i].idx;
 
  693          if (idx < pfda.size() &&
 
  694              source.pfds_[i].pfd->fd == pfda[idx].fd)
 
  695            source.pfds_[i].pfd->revents = pfda[idx].revents;
 
  697            source.pfds_[i].idx = 4294967295U; 
 
  700      bool need_dispatch = source.check (state);
 
  702      if (source.loop_ != 
this)
 
  706          dispatch_priority_ = 
std::max (dispatch_priority_, source.priority_); 
 
  707          source.loop_state_ = NEEDS_DISPATCH;
 
  710        source.loop_state_ = WAITING;
 
  712  return dispatch_priority_ > UNDEFINED_PRIORITY;
 
  716EventLoop::dispatch_source_Lm (LoopState &state)
 
  720  EventSourceP dispatch_source = NULL;                  
 
  721  for (
auto lit = poll_sources_.
begin(); lit != poll_sources_.
end(); lit++)
 
  723      EventSourceP &source = *lit;
 
  724      if (source->loop_ == 
this &&                      
 
  725          source->priority_ == dispatch_priority_ &&    
 
  726          source->loop_state_ == NEEDS_DISPATCH)
 
  728          dispatch_source = source;
 
  732  dispatch_priority_ = UNDEFINED_PRIORITY;
 
  736      dispatch_source->loop_state_ = WAITING;
 
  737      const bool old_was_dispatching = dispatch_source->was_dispatching_;
 
  738      dispatch_source->was_dispatching_ = dispatch_source->dispatching_;
 
  739      dispatch_source->dispatching_ = 
true;
 
  741      const bool keep_alive = dispatch_source->dispatch (state);
 
  743      dispatch_source->dispatching_ = dispatch_source->was_dispatching_;
 
  744      dispatch_source->was_dispatching_ = old_was_dispatching;
 
  745      if (dispatch_source->loop_ == 
this && !keep_alive)
 
  746        remove_source_Lm (dispatch_source);
 
  751MainLoop::iterate_loops_Lm (LoopState &state, 
bool may_block, 
bool may_dispatch)
 
  755  PollFD reserved_pfd_mem[7];   
 
  756  QuickPfdArray pfda (
ARRAY_SIZE (reserved_pfd_mem), reserved_pfd_mem); 
 
  759  const uint wakeup_idx = 0; 
 
  762  const size_t nrloops = loops_.size(); 
 
  763  EventLoopP loops[nrloops];
 
  764  for (
size_t i = 0; i < nrloops; i++)
 
  765    loops[i] = loops_[i];
 
  767  state.phase = state.COLLECT;
 
  768  state.seen_primary = 
false;
 
  769  for (
size_t i = 0; i < nrloops; i++)
 
  770    loops[i]->collect_sources_Lm (state);
 
  772  bool any_dispatchable = 
false;
 
  773  state.phase = state.PREPARE;
 
  776  bool dispatchable[nrloops + 1];        
 
  777  for (
size_t i = 0; i < nrloops; i++)
 
  779      dispatchable[i] = loops[i]->prepare_sources_Lm (state, pfda);
 
  780      any_dispatchable |= dispatchable[i];
 
  783  ASE_UNUSED 
const int gfirstfd = pfda.size();
 
  788      dispatchable[nrloops] = g_main_context_prepare (gcontext_, &gpriority) != 0;
 
  789      any_dispatchable |= dispatchable[nrloops];
 
  791      pfda.resize (pfda.capacity());
 
  792      int gnfds = g_main_context_query (gcontext_, gpriority, >imeout, mk_gpollfd (&pfda[gfirstfd]), pfda.size() - gfirstfd);
 
  793      while (gnfds >= 0 && 
size_t (gnfds) != pfda.size() - gfirstfd)
 
  795          pfda.resize (gfirstfd + gnfds);
 
  797          gnfds = g_main_context_query (gcontext_, gpriority, >imeout, mk_gpollfd (&pfda[gfirstfd]), pfda.size() - gfirstfd);
 
  800        state.timeout_usecs = 
MIN (state.timeout_usecs, gtimeout * 
int64 (1000));
 
  804    dispatchable[nrloops] = 
false;
 
  806  int64 timeout_msecs = state.timeout_usecs / 1000;
 
  807  if (state.timeout_usecs > 0 && timeout_msecs <= 0)
 
  809  if (!may_block || any_dispatchable)
 
  811  state.timeout_usecs = 0;
 
  815    presult = 
poll ((
struct pollfd*) &pfda[0], pfda.size(), 
std::min (timeout_msecs, 
int64 (2147483647))); 
 
  816  while (presult < 0 && errno == EAGAIN); 
 
  818  if (presult < 0 && errno != EINTR)
 
  819    warning (
"MainLoop: poll() failed: %s", 
strerror());
 
  820  else if (pfda[wakeup_idx].revents)
 
  823  state.phase = state.CHECK;
 
  825  int16 max_dispatch_priority = -32768;
 
  826  for (
size_t i = 0; i < nrloops; i++)
 
  828      dispatchable[i] |= loops[i]->check_sources_Lm (state, pfda);
 
  829      if (!dispatchable[i])
 
  831      any_dispatchable = 
true;
 
  832      max_dispatch_priority = 
std::max (max_dispatch_priority, loops[i]->dispatch_priority_);
 
  834  bool priority_ascension = 
false;      
 
  836    priority_ascension = 
true;
 
  841      dispatchable[nrloops] = g_main_context_check (gcontext_, gpriority, mk_gpollfd (&pfda[gfirstfd]), pfda.size() - gfirstfd);
 
  842      any_dispatchable |= dispatchable[nrloops];
 
  846  if (may_dispatch && any_dispatchable)
 
  848      const size_t gloop = 
ASE_UNLIKELY (gcontext_) && dispatchable[nrloops] ? 1 : 0;
 
  849      const size_t maxloops = nrloops + gloop; 
 
  853          index = rr_index_++ % maxloops; 
 
  854          if (!dispatchable[index])
 
  856          if (index < nrloops && loops[index]->dispatch_priority_ < max_dispatch_priority)
 
  858          if (priority_ascension && index >= nrloops)
 
  862      state.phase = state.DISPATCH;
 
  863      if (index >= nrloops)
 
  866          g_main_context_dispatch (gcontext_);
 
  870        loops[index]->dispatch_source_Lm (state); 
 
  873  state.phase = state.NONE;
 
  875  for (
size_t i = 0; i < nrloops; i++)
 
  877      loops[i]->unpoll_sources_U(); 
 
  881  return any_dispatchable; 
 
  900  this->add_loop_L (*sub_loop);
 
 
  905EventSource::EventSource () :
 
  909  priority_ (UNDEFINED_PRIORITY),
 
  913  was_dispatching_ (0),
 
  918EventSource::n_pfds ()
 
  948  primary_ = is_primary;
 
 
  954  return dispatching_ && was_dispatching_;
 
 
  960  const uint idx = n_pfds();
 
  961  uint npfds = idx + 1;
 
  962  pfds_ = (typeof (pfds_)) 
realloc (pfds_, 
sizeof (pfds_[0]) * (npfds + 1));
 
  964    fatal_error (
"EventSource: out of memory");
 
  965  pfds_[npfds].idx = 4294967295U; 
 
  966  pfds_[npfds].pfd = NULL;
 
  967  pfds_[idx].idx = 4294967295U; 
 
  968  pfds_[idx].pfd = pfd;
 
 
  974  uint idx, npfds = n_pfds();
 
  975  for (idx = 0; idx < npfds; idx++)
 
  976    if (pfds_[idx].pfd == pfd)
 
  980      pfds_[idx].idx = 4294967295U; 
 
  981      pfds_[idx].pfd = pfds_[npfds - 1].pfd;
 
  982      pfds_[idx].idx = pfds_[npfds - 1].idx;
 
  983      pfds_[npfds - 1].idx = 4294967295U; 
 
  984      pfds_[npfds - 1].pfd = NULL;
 
  987    warning (
"EventSource: unremovable PollFD: %p (fd=%d)", pfd, pfd->fd);
 
 
  991EventSource::destroy ()
 
 1001EventSource::~EventSource ()
 
 1009DispatcherSource::DispatcherSource (
const DispatcherSlot &slot) :
 
 1013DispatcherSource::~DispatcherSource ()
 
 1021  return slot_ (state);
 
 
 1027  return slot_ (state);
 
 
 1033  return slot_ (state);
 
 
 1037DispatcherSource::destroy()
 
 1040  state.phase = state.DESTROY;
 
 1045USignalSource::USignalSource (
int8 signum, 
const USignalSlot &slot) :
 
 1046  slot_ (slot), signum_ (signum)
 
 1048  const uint s = 128 + signum_;
 
 1053USignalSource::~USignalSource ()
 
 1064  const uint s = 128 + signum;
 
 1065  const uint index = s / 32;
 
 1066  const uint shift = s % 32;
 
 1067  usignals_notified[index] |= 1 << shift;
 
 
 1073  return usignals_notified[index_] & (1 << shift_);
 
 
 1079  return usignals_notified[index_] & (1 << shift_);
 
 
 1085  usignals_notified[index_] &= ~(1 << shift_);
 
 1086  return slot_ (signum_);
 
 
 1090USignalSource::destroy()
 
 1094write_uint (uint32_t i)
 
 1097  char *c = &a.back();
 
 1100  *c = 
'0' + (i % 10);
 
 1103    *(--c) = 
'0' + (i % 10);
 
 1107    memmove (&a[0], c, &a.back() + 1 - c);
 
 1113USignalSource::install_sigaction (
int8 signum)
 
 1116  action.sa_handler = [] (
int signum) {
 
 1118      constexpr size_t N = 1024;
 
 1119      char buf[N] = __FILE__ 
":";
 
 1120      strncat (buf, &write_uint (__LINE__)[0], N);
 
 1121      strncat (buf, 
": sa_handler: signal=", N);
 
 1122      strncat (buf, &write_uint (signum)[0], N);
 
 1124      ::write (2, buf, strlen (buf));
 
 1129  action.sa_flags = SA_NOMASK;
 
 1136SigchldSource::SigchldSource (int64_t pid, 
const SigchldSlot &slot) :
 
 1137  slot_ (slot), pid_ (pid)
 
 1141    action.sa_handler = [] (
int signum) {
 
 1145    action.sa_flags = SA_NOMASK;
 
 1150SigchldSource::~SigchldSource()
 
 1156  return pid_ && sigchld_counter_ != sigchld_counter;
 
 
 1162  return pid_ && sigchld_counter_ != sigchld_counter;
 
 
 1169    sigchld_counter_ = sigchld_counter;
 
 1172    const pid_t child_pid = wait4 (pid_, &status, WNOHANG, 
nullptr);
 
 1173    if (child_pid > 0) {
 
 1174      slot_ (pid_, status);
 
 1176      struct rusage ru {}; 
 
 1177      printf (
"  Child Pid %d user time: %ld.%06ld sec\n", child_pid, ru.ru_utime.tv_sec, ru.ru_utime.tv_usec);
 
 1178      printf (
"  System time: %ld.%06ld sec\n", ru.ru_stime.tv_sec, ru.ru_stime.tv_usec);
 
 1179      printf (
"  Max RSS: %ld KB\n", ru.ru_maxrss);
 
 1180      printf (
"  Page faults: %ld\n", ru.ru_minflt);
 
 1181      printf (
"  I/O operations: %ld\n", ru.ru_inblock + ru.ru_oublock);
 
 1182      printf (
"  Voluntary context switches: %ld\n", ru.ru_nvcsw);
 
 1183      printf (
"  Involuntary context switches: %ld\n", ru.ru_nivcsw);
 
 1186      if (WIFEXITED (status) || WIFSIGNALED (status)) {
 
 
 1197SigchldSource::destroy ()
 
 1203TimedSource::TimedSource (
const VoidSlot &slot, 
uint initial_interval_msecs, 
uint repeat_interval_msecs) :
 
 1205  interval_msecs_ (repeat_interval_msecs), first_interval_ (true),
 
 1206  oneshot_ (true), void_slot_ (slot)
 
 1209TimedSource::TimedSource (
const BoolSlot &slot, 
uint initial_interval_msecs, 
uint repeat_interval_msecs) :
 
 1211  interval_msecs_ (repeat_interval_msecs), first_interval_ (true),
 
 1212  oneshot_ (false), bool_slot_ (slot)
 
 1220  if (!first_interval_)
 
 1222      uint64 interval = interval_msecs_ * 1000ULL;
 
 1227  return 0 == *timeout_usecs_p;
 
 
 1239  bool repeat = 
false;
 
 1240  first_interval_ = 
false;
 
 1241  if (oneshot_ && void_slot_ != NULL)
 
 1243  else if (!oneshot_ && bool_slot_ != NULL)
 
 1244    repeat = bool_slot_ ();
 
 
 1250TimedSource::~TimedSource ()
 
 1253    void_slot_.~VoidSlot();
 
 1255    bool_slot_.~BoolSlot();
 
 1271PollFDSource::PollFDSource (
const BPfdSlot &slot, 
int fd, 
const String &mode) :
 
 1272  pfd_ ((PollFD) { fd, 0, 0 }),
 
 1273  never_close_ (strchr (mode.c_str(), 
'C') != NULL),
 
 1274  oneshot_ (
false), bool_poll_slot_ (slot)
 
 1279PollFDSource::PollFDSource (
const VPfdSlot &slot, 
int fd, 
const String &mode) :
 
 1280  pfd_ ((PollFD) { fd, 0, 0 }),
 
 1281  never_close_ (strchr (mode.c_str(), 
'C') != NULL),
 
 1282  oneshot_ (
true), void_poll_slot_ (slot)
 
 1288PollFDSource::construct (
const String &mode)
 
 1297      const long lflags = 
fcntl (pfd_.fd, F_GETFL, 0);
 
 1298      long nflags = lflags;
 
 1299      if (strchr (mode.c_str(), 
'b'))
 
 1300        nflags &= ~long (O_NONBLOCK);
 
 1301      else if (strchr (mode.c_str(), 
'B'))
 
 1302        nflags |= O_NONBLOCK;
 
 1303      if (nflags != lflags)
 
 1307            err = 
fcntl (pfd_.fd, F_SETFL, nflags);
 
 1308          while (err < 0 && (errno == EINTR || errno == EAGAIN));
 
 1323  return pfd_.fd < 0 || pfd_.revents != 0;
 
 
 1329  bool keep_alive = !oneshot_;
 
 1330  if (oneshot_ && void_poll_slot_ != NULL)
 
 1331    void_poll_slot_ (pfd_);
 
 1332  else if (!oneshot_ && bool_poll_slot_ != NULL)
 
 1333    keep_alive = bool_poll_slot_ (pfd_);
 
 1337      if (!never_close_ && pfd_.fd >= 0)
 
 
 1345PollFDSource::destroy()
 
 1348  if (!never_close_ && pfd_.fd >= 0)
 
 1353PollFDSource::~PollFDSource ()
 
 1356    void_poll_slot_.~VPfdSlot();
 
 1358    bool_poll_slot_.~BPfdSlot();
 
virtual bool dispatch(const LoopState &state)
Dispatch source, returns if it should be kept alive.
 
virtual bool prepare(const LoopState &state, int64 *timeout_usecs_p)
Prepare the source for dispatching (true return) or polling (false).
 
virtual bool check(const LoopState &state)
Check the source and its PollFD descriptors for dispatching (true return).
 
bool opened()
Indicates whether eventfd has been opened.
 
void flush()
Clear pending wakeups.
 
int inputfd()
Returns the file descriptor for POLLIN.
 
void wakeup()
Wakeup polling end.
 
Loop object, polling for events and executing callbacks in accordance.
 
bool has_primary(void)
Indicates whether loop contains primary sources.
 
void wakeup()
Wakeup loop from polling.
 
bool clear_source(uint *id_pointer)
Remove source if id_pointer and *id_pointer are valid.
 
void remove(uint id)
Removes a source from loop, the source must be present.
 
static const int16 PRIORITY_CEILING
Internal upper limit, don't use.
 
bool exec_once(uint delay_ms, uint *once_id, const VoidSlot &vfunc, int priority=PRIORITY_NORMAL)
Execute a callback once on SIGCHLD for pid.
 
MainLoop * main_loop() const
Get the main loop for this loop.
 
static const int16 PRIORITY_ASCENT
Threshold for priorization across different loops.
 
bool try_remove(uint id)
Tries to remove a source, returns if successfull.
 
uint add(EventSourceP loop_source, int priority=PRIORITY_NORMAL)
Adds a new source to the loop with custom priority.
 
bool primary() const
Indicate whether this source is primary.
 
void add_poll(PollFD *const pfd)
Add a PollFD descriptors for poll(2) and check().
 
void loop_remove()
Remove this source from its event loop if any.
 
void remove_poll(PollFD *const pfd)
Remove a previously added PollFD.
 
bool recursion() const
Indicates wether the source is currently in recursion.
 
bool may_recurse() const
Indicates if this source may recurse.
 
An EventLoop implementation that offers public API for running the loop.
 
EventLoopP create_sub_loop()
Creates a new event loop that is run as part of this main loop.
 
void quit(int quit_code=0)
Cause run() to return with quit_code.
 
static MainLoopP create()
Create a MainLoop shared pointer handle.
 
bool pending()
Check if iterate() needs to be called for dispatching.
 
int run()
Run loop iterations until a call to quit() or finishable becomes true.
 
bool set_g_main_context(GlibGMainContext *glib_main_context)
Set context to integrate with a GLib GMainContext loop.
 
void iterate_pending()
Call iterate() until no immediate dispatching is needed.
 
bool running()
Indicates if quit() has been called already.
 
bool finishable()
Indicates wether this loop has no primary sources left to process.
 
std::mutex & mutex()
Provide access to the mutex associated with this main loop.
 
bool iterate(bool block)
Perform one loop iteration and return whether more iterations are needed.
 
virtual bool dispatch(const LoopState &state)
Dispatch source, returns if it should be kept alive.
 
virtual bool prepare(const LoopState &state, int64 *timeout_usecs_p)
Prepare the source for dispatching (true return) or polling (false).
 
virtual bool check(const LoopState &state)
Check the source and its PollFD descriptors for dispatching (true return).
 
virtual bool dispatch(const LoopState &state)
Dispatch source, returns if it should be kept alive.
 
virtual bool prepare(const LoopState &state, int64 *timeout_usecs_p)
Prepare the source for dispatching (true return) or polling (false).
 
virtual bool check(const LoopState &state)
Check the source and its PollFD descriptors for dispatching (true return).
 
virtual bool check(const LoopState &state)
Check the source and its PollFD descriptors for dispatching (true return).
 
virtual bool prepare(const LoopState &state, int64 *timeout_usecs_p)
Prepare the source for dispatching (true return) or polling (false).
 
virtual bool dispatch(const LoopState &state)
Dispatch source, returns if it should be kept alive.
 
virtual bool dispatch(const LoopState &state)
Dispatch source, returns if it should be kept alive.
 
virtual bool prepare(const LoopState &state, int64 *timeout_usecs_p)
Prepare the source for dispatching (true return) or polling (false).
 
static void raise(int8 signum)
Flag a unix signal being raised, this function may be called from any thread at any time.
 
virtual bool check(const LoopState &state)
Check the source and its PollFD descriptors for dispatching (true return).
 
T compare_exchange_strong(T... args)
 
#define ASE_ASSERT(expr)
Issue an assertion warning if expr evaluates to false.
 
#define ASE_UNLIKELY(expr)
Compiler hint to optimize for expr evaluating to false.
 
#define assert_return(expr,...)
Return from the current function if expr is unmet and issue an assertion warning.
 
#define MIN(a, b)
Yield minimum of a and b.
 
#define return_unless(cond,...)
Return silently if cond does not evaluate to true with return value ...
 
#define ARRAY_SIZE(array)
Yield the number of C array elements.
 
#define UNLIKELY(cond)
Hint to the compiler to optimize for cond == FALSE.
 
#define ISLIKELY(cond)
Hint to the compiler to optimize for cond == TRUE.
 
The Anklang C++ API namespace.
 
uint64_t uint64
A 64-bit unsigned integer, use PRI*64 in format strings.
 
int16_t int16
A 16-bit signed integer.
 
int8_t int8
An 8-bit signed integer.
 
int64_t int64
A 64-bit unsigned integer, use PRI*64 in format strings.
 
std::string String
Convenience alias for std::string.
 
uint32_t uint
Provide 'uint' as convenience type.
 
uint64 timestamp_realtime()
Return the current time as uint64 in µseconds.
 
uint64 current_time_usecs
Equals timestamp_realtime() as of prepare() and check().
 
Mirrors struct pollfd for poll(3posix)
 
@ RDNORM
reading data will not block
 
@ HUP
file descriptor closed
 
@ WRNORM
writing data will not block
 
@ PRI
urgent data available
 
@ RDBAND
reading priority data will not block
 
@ OUT
writing data will not block
 
@ WRBAND
writing priority data will not block