3434#include < limits>
3535#include < functional>
3636#include < unordered_map>
37- #endif
37+
38+ namespace zmq
39+ {
40+ // socket ref or native file descriptor for poller
41+ class poller_ref_t
42+ {
43+ public:
44+ enum RefType
45+ {
46+ RT_SOCKET,
47+ RT_FD
48+ };
49+
50+ poller_ref_t () : poller_ref_t (socket_ref{})
51+ {}
52+
53+ poller_ref_t (const zmq::socket_ref& socket) : data{RT_SOCKET, socket, {}}
54+ {}
55+
56+ poller_ref_t (zmq::fd_t fd) : data{RT_FD, {}, fd}
57+ {}
58+
59+ size_t hash () const ZMQ_NOTHROW
60+ {
61+ std::size_t h = 0 ;
62+ hash_combine (h, std::get<0 >(data));
63+ hash_combine (h, std::get<1 >(data));
64+ hash_combine (h, std::get<2 >(data));
65+ return h;
66+ }
67+
68+ bool operator == (const poller_ref_t & o) const ZMQ_NOTHROW
69+ {
70+ return data == o.data ;
71+ }
72+
73+ private:
74+ template <class T >
75+ static void hash_combine (std::size_t & seed, const T& v) ZMQ_NOTHROW
76+ {
77+ std::hash<T> hasher;
78+ seed ^= hasher (v) + 0x9e3779b9 + (seed<<6 ) + (seed>>2 );
79+ }
80+
81+ std::tuple<int , zmq::socket_ref, zmq::fd_t > data;
82+
83+ }; // class poller_ref_t
84+
85+ } // namespace zmq
86+
87+ // std::hash<> specialization for std::unordered_map
88+ template <> struct std ::hash<zmq::poller_ref_t >
89+ {
90+ size_t operator ()(const zmq::poller_ref_t & ref) const ZMQ_NOTHROW
91+ {
92+ return ref.hash ();
93+ }
94+ };
95+ #endif // ZMQ_CPP11
3896
3997namespace zmq
4098{
@@ -683,10 +741,12 @@ class active_poller_t
683741
684742 void add (zmq::socket_ref socket, event_flags events, handler_type handler)
685743 {
744+ const poller_ref_t ref{socket};
745+
686746 if (!handler)
687- throw std::invalid_argument (" null handler in active_poller_t::add" );
747+ throw std::invalid_argument (" null handler in active_poller_t::add (socket) " );
688748 auto ret = handlers.emplace (
689- socket , std::make_shared<handler_type>(std::move (handler)));
749+ ref , std::make_shared<handler_type>(std::move (handler)));
690750 if (!ret.second )
691751 throw error_t (EINVAL); // already added
692752 try {
@@ -695,7 +755,28 @@ class active_poller_t
695755 }
696756 catch (...) {
697757 // rollback
698- handlers.erase (socket);
758+ handlers.erase (ref);
759+ throw ;
760+ }
761+ }
762+
763+ void add (fd_t fd, event_flags events, handler_type handler)
764+ {
765+ const poller_ref_t ref{fd};
766+
767+ if (!handler)
768+ throw std::invalid_argument (" null handler in active_poller_t::add (fd)" );
769+ auto ret = handlers.emplace (
770+ ref, std::make_shared<handler_type>(std::move (handler)));
771+ if (!ret.second )
772+ throw error_t (EINVAL); // already added
773+ try {
774+ base_poller.add (fd, events, ret.first ->second .get ());
775+ need_rebuild = true ;
776+ }
777+ catch (...) {
778+ // rollback
779+ handlers.erase (ref);
699780 throw ;
700781 }
701782 }
@@ -707,11 +788,23 @@ class active_poller_t
707788 need_rebuild = true ;
708789 }
709790
791+ void remove (fd_t fd)
792+ {
793+ base_poller.remove (fd);
794+ handlers.erase (fd);
795+ need_rebuild = true ;
796+ }
797+
710798 void modify (zmq::socket_ref socket, event_flags events)
711799 {
712800 base_poller.modify (socket, events);
713801 }
714802
803+ void modify (fd_t fd, event_flags events)
804+ {
805+ base_poller.modify (fd, events);
806+ }
807+
715808 size_t wait (std::chrono::milliseconds timeout)
716809 {
717810 if (need_rebuild) {
@@ -741,7 +834,9 @@ class active_poller_t
741834 bool need_rebuild{false };
742835
743836 poller_t <handler_type> base_poller{};
744- std::unordered_map<socket_ref, std::shared_ptr<handler_type>> handlers{};
837+
838+ std::unordered_map<zmq::poller_ref_t , std::shared_ptr<handler_type>> handlers{};
839+
745840 std::vector<decltype (base_poller)::event_type> poller_events{};
746841 std::vector<std::shared_ptr<handler_type>> poller_handlers{};
747842}; // class active_poller_t
0 commit comments