Browse Source

Update bundled Dasynq to 1.2.3

Davin McCall 1 year ago
parent
commit
3538dd15c3

+ 1 - 1
dasynq/include/dasynq.h

@@ -1093,7 +1093,7 @@ class event_loop
     void interrupt_if_necessary()
     {
         wait_lock.lock();
-        bool attn_q_empty = attn_waitqueue.is_empty(); // (always false for single-threaded loops)
+        bool attn_q_empty = attn_waitqueue.is_empty(); // (always true for single-threaded loops)
         wait_lock.unlock();
 
         if (! attn_q_empty) {

+ 7 - 7
dasynq/include/dasynq/basewatchers.h

@@ -115,11 +115,11 @@ namespace dprivate {
     {
         public:
         watch_type_t watchType;
-        int active : 1;    // currently executing handler?
-        int deleteme : 1;  // delete when handler finished?
-        int emulatefd : 1; // emulate file watch (by re-queueing)
-        int emulate_enabled : 1;   // whether an emulated watch is enabled
-        int child_termd : 1;  // child process has terminated
+        unsigned active : 1;    // currently executing handler?
+        unsigned deleteme : 1;  // delete when handler finished?
+        unsigned emulatefd : 1; // emulate file watch (by re-queueing)
+        unsigned emulate_enabled : 1;   // whether an emulated watch is enabled
+        unsigned child_termd : 1;  // child process has terminated
 
         prio_queue::handle_t heap_handle;
         int priority;
@@ -244,8 +244,8 @@ namespace dprivate {
         // used; it exists mainly so that it can be queued independently of the primary watcher.
         base_watcher out_watcher {watch_type_t::SECONDARYFD};
 
-        int read_removed : 1; // read watch removed?
-        int write_removed : 1; // write watch removed?
+        unsigned read_removed : 1; // read watch removed?
+        unsigned write_removed : 1; // write watch removed?
     };
 
     class base_child_watcher : public base_watcher

+ 4 - 2
dasynq/include/dasynq/epoll.h

@@ -138,9 +138,11 @@ template <class Base> class epoll_loop : public Base
             else {
                 int flags = 0;
                 (events[i].events & EPOLLIN) && (flags |= IN_EVENTS);
-                (events[i].events & EPOLLHUP) && (flags |= IN_EVENTS);
                 (events[i].events & EPOLLOUT) && (flags |= OUT_EVENTS);
-                (events[i].events & EPOLLERR) && (flags |= IN_EVENTS | OUT_EVENTS | ERR_EVENTS);
+                // We mustn't introduce IN/OUT events for error conditions as we don't know which are being
+                // watched! Just set ERR_EVENTS.
+                (events[i].events & EPOLLHUP) && (flags |= ERR_EVENTS);
+                (events[i].events & EPOLLERR) && (flags |= ERR_EVENTS);
                 auto r = Base::receive_fd_event(*this, fd_r(), ptr, flags);
                 if (std::get<0>(r) != 0) {
                     enable_fd_watch_nolock(fd_r().get_fd(std::get<1>(r)), ptr, std::get<0>(r));

+ 1 - 1
dasynq/include/dasynq/interrupt.h

@@ -93,7 +93,7 @@ template <typename Base, typename Mutex> class interrupt_channel : public Base
             eventfd_read(pipe_r_fd, &val);
 #endif
             if (Base::traits_t::supports_non_oneshot_fd) {
-                // If the loop mechanism actually persists none-oneshot marked watches, we don't need
+                // If the loop mechanism actually persists non-oneshot marked watches, we don't need
                 // to re-enable:
                 return std::make_tuple(0, typename Base::traits_t::fd_s(pipe_r_fd));
             }

+ 9 - 7
dasynq/include/dasynq/pselect.h

@@ -29,13 +29,14 @@ template <class Base> class pselect_events : public signal_events<Base, false>
     {
         std::lock_guard<decltype(Base::lock)> guard(Base::lock);
 
-        // Note: if error is set, report read-ready.
+        // Note: if error is set, we expect read or write is also set.
 
         for (int i = 0; i <= max_fd; i++) {
-            if (FD_ISSET(i, read_set_p) || FD_ISSET(i, error_set_p)) {
+            if (FD_ISSET(i, read_set_p)) {
                 if (FD_ISSET(i, &read_set) && rd_udata[i] != nullptr) {
                     // report read
-                    auto r = Base::receive_fd_event(*this, fd_r(i), rd_udata[i], IN_EVENTS);
+                	int events = IN_EVENTS | (FD_ISSET(i, error_set_p) ? ERR_EVENTS : 0);
+                    auto r = Base::receive_fd_event(*this, fd_r(i), rd_udata[i], events);
                     if (std::get<0>(r) == 0) {
                         FD_CLR(i, &read_set);
                     }
@@ -47,7 +48,8 @@ template <class Base> class pselect_events : public signal_events<Base, false>
             if (FD_ISSET(i, write_set_p)) {
                 if (FD_ISSET(i, &write_set) && wr_udata[i] != nullptr) {
                     // report write
-                    auto r = Base::receive_fd_event(*this, fd_r(i), wr_udata[i], OUT_EVENTS);
+                	int events = OUT_EVENTS | (FD_ISSET(i, error_set_p) ? ERR_EVENTS : 0);
+                    auto r = Base::receive_fd_event(*this, fd_r(i), wr_udata[i], events);
                     if (std::get<0>(r) == 0) {
                         FD_CLR(i, &write_set);
                     }
@@ -229,9 +231,9 @@ template <class Base> class pselect_events : public signal_events<Base, false>
         // Check whether any timers are pending, and what the next timeout is.
         this->process_monotonic_timers(do_wait, ts, wait_ts);
 
-        fd_set read_set_c;
-        fd_set write_set_c;
-        fd_set err_set;
+        volatile fd_set read_set_c;
+        volatile fd_set write_set_c;
+        volatile fd_set err_set;
 
         read_set_c = read_set;
         write_set_c = write_set;

+ 10 - 8
dasynq/include/dasynq/select.h

@@ -18,7 +18,7 @@
 #include "config.h"
 #include "signal.h"
 
-// "pselect"-based event loop mechanism.
+// "select"-based event loop mechanism.
 //
 
 namespace dasynq {
@@ -86,13 +86,14 @@ template <class Base> class select_events : public signal_events<Base, true>
     {
         std::lock_guard<decltype(Base::lock)> guard(Base::lock);
 
-        // Note: if error is set, report read-ready.
+        // Note: if error is set, we expect read or write is also set.
 
         for (int i = 0; i <= max_fd; i++) {
-            if (FD_ISSET(i, read_set_p) || FD_ISSET(i, error_set_p)) {
+            if (FD_ISSET(i, read_set_p)) {
                 if (FD_ISSET(i, &read_set) && rd_udata[i] != nullptr) {
                     // report read
-                    auto r = Base::receive_fd_event(*this, fd_r(i), rd_udata[i], IN_EVENTS);
+                	int events = IN_EVENTS | (FD_ISSET(i, error_set_p) ? ERR_EVENTS : 0);
+                    auto r = Base::receive_fd_event(*this, fd_r(i), rd_udata[i], events);
                     if (std::get<0>(r) == 0) {
                         FD_CLR(i, &read_set);
                     }
@@ -104,7 +105,8 @@ template <class Base> class select_events : public signal_events<Base, true>
             if (FD_ISSET(i, write_set_p)) {
                 if (FD_ISSET(i, &write_set) && wr_udata[i] != nullptr) {
                     // report write
-                    auto r = Base::receive_fd_event(*this, fd_r(i), wr_udata[i], OUT_EVENTS);
+                	int events = OUT_EVENTS | (FD_ISSET(i, error_set_p) ? ERR_EVENTS : 0);
+                    auto r = Base::receive_fd_event(*this, fd_r(i), wr_udata[i], events);
                     if (std::get<0>(r) == 0) {
                         FD_CLR(i, &write_set);
                     }
@@ -287,9 +289,9 @@ template <class Base> class select_events : public signal_events<Base, true>
         // Check whether any timers are pending, and what the next timeout is.
         this->process_monotonic_timers(do_wait, ts, wait_ts);
 
-        fd_set read_set_c;
-        fd_set write_set_c;
-        fd_set err_set;
+        volatile fd_set read_set_c;
+        volatile fd_set write_set_c;
+        volatile fd_set err_set;
 
         read_set_c = read_set;
         write_set_c = write_set;

+ 12 - 11
dasynq/include/dasynq/stableheap.h

@@ -23,13 +23,13 @@ class stable_prio
     uint64_t order;
     
     template <typename ...U>
-    stable_prio(uint64_t o, U... u) : p(u...), order(o)
+    stable_prio(uint64_t o, U... u) noexcept(noexcept(P(u...))): p(u...), order(o)
     {
     }
     
     // zero-argument constructor should not really be needed, but some
     // heap implementations aren't yet perfect.
-    stable_prio()
+    stable_prio() noexcept
     {
     }
 };
@@ -39,6 +39,7 @@ class compare_stable_prio
 {
     public:
     bool operator()(const stable_prio<P> &a, const stable_prio<P> &b)
+            noexcept(noexcept(C()) && noexcept(std::declval<C>()(std::declval<P>(),std::declval<P>())))
     {
         C lt;
         if (lt(a.p, b.p)) {
@@ -79,47 +80,47 @@ class stable_heap : private H<T,stable_prio<P>,compare_stable_prio<P,C>>
         Base::allocate(hnd, std::forward<U>(u)...);
     }
 
-    static void init_handle(handle_t &hndl)
+    static void init_handle(handle_t &hndl) noexcept(noexcept(std::declval<Base>().init_handle(hndl)))
     {
         Base::init_handle(hndl);
     }
 
-    T &node_data(handle_t &hndl)
+    T &node_data(handle_t &hndl) noexcept(noexcept(std::declval<Base>().node_data(hndl)))
     {
         return Base::node_data(hndl);
     }
 
-    bool is_queued(handle_t & hnd)
+    bool is_queued(handle_t & hnd) noexcept(noexcept(std::declval<Base>().is_queued(hnd)))
     {
         return Base::is_queued(hnd);
     }
 
-    decltype(std::declval<Base>().get_root()) get_root()
+    decltype(std::declval<Base>().get_root()) get_root() noexcept(noexcept(std::declval<Base>().get_root()))
     {
         return Base::get_root();
     }
     
-    void pull_root()
+    void pull_root() noexcept(noexcept(std::declval<Base>().pull_root()))
     {
         Base::pull_root();
     }
     
-    void deallocate(handle_t_r index)
+    void deallocate(handle_t_r index) noexcept(noexcept(std::declval<Base>().deallocate(index)))
     {
         Base::deallocate(index);
     }
     
-    void remove(handle_t_r hnd)
+    void remove(handle_t_r hnd) noexcept(noexcept(std::declval<Base>().remove(hnd)))
     {
         Base::remove(hnd);
     }
     
-    bool empty()
+    bool empty() noexcept(noexcept(std::declval<Base>().empty()))
     {
         return Base::empty();
     }
 
-    unsigned size()
+    unsigned size() noexcept(noexcept(std::declval<Base>().size()))
     {
         return Base::size();
     }

+ 4 - 5
dasynq/include/dasynq/timerfd.h

@@ -104,14 +104,13 @@ template <class Base> class timer_fd_events : public timer_base<Base>
     {
         if (userdata == &timerfd_fd) {
             process_timer(clock_type::MONOTONIC, timerfd_fd);
-            return std::make_tuple(IN_EVENTS, typename traits_t::fd_s(timerfd_fd));
+            unsigned re_enable = (Base::traits_t::supports_non_oneshot_fd ? 0 : IN_EVENTS);
+            return std::make_tuple(re_enable, typename traits_t::fd_s(timerfd_fd));
         }
         else if (userdata == &systemtime_fd) {
             process_timer(clock_type::SYSTEM, systemtime_fd);
-            if (Base::traits_t::supports_non_oneshot_fd) {
-                return std::make_tuple(0, typename traits_t::fd_s(systemtime_fd));
-            }
-            return std::make_tuple(IN_EVENTS, typename traits_t::fd_s(systemtime_fd));
+            unsigned re_enable = (Base::traits_t::supports_non_oneshot_fd ? 0 : IN_EVENTS);
+            return std::make_tuple(re_enable, typename traits_t::fd_s(systemtime_fd));
         }
         else {
             return Base::receive_fd_event(loop_mech, fd_r_a, userdata, flags);