ZeroMQ: How to cast a pollitem_t item, used in Poller, back to a ZeroMQ socket?

风流意气都作罢 提交于 2020-01-14 03:28:07

问题


As title says, when using zmq::poll with cppzmq, I'd love to avoid hardcoding the translation of ZeroMQ sockets into pollitem_t item(s) for polling.

But it seems that I'm not allowed to convert a void* pollitem_t::socket back to a zmq socket.

I noticed that the official sample code just hardcoded the socket after polling.

//
//  Reading from multiple sockets in C++
//  This version uses zmq_poll()
//
// Olivier Chamoux <olivier.chamoux@fr.thalesgroup.com>

#include "zhelpers.hpp"

int main (int argc, char *argv[])
{
    zmq::context_t context(1);

    //  Connect to task ventilator
    zmq::socket_t receiver(context, ZMQ_PULL);
    receiver.connect("tcp://localhost:5557");

    //  Connect to weather server
    zmq::socket_t subscriber(context, ZMQ_SUB);
    subscriber.connect("tcp://localhost:5556");
    subscriber.setsockopt(ZMQ_SUBSCRIBE, "10001 ", 6);

    //  Initialize poll set
    zmq::pollitem_t items [] = {
        { static_cast<void*>(receiver), 0, ZMQ_POLLIN, 0 },
        { static_cast<void*>(subscriber), 0, ZMQ_POLLIN, 0 }
    };
    //  Process messages from both sockets
    while (1) {
        zmq::message_t message;
        zmq::poll (&items [0], 2, -1);

        if (items [0].revents & ZMQ_POLLIN) {
            receiver.recv(&message);
            //  Process task
        }
        if (items [1].revents & ZMQ_POLLIN) {
            subscriber.recv(&message);
            //  Process weather update
        }
    }
    return 0;
}

Hence the question:

Is it impossible to avoid hardcoding sockets in this case?


回答1:


Puzzled this together from the zmq.hpp header:

zmq::poller_t poller;
poller.add({from_handle, receiver.handle()}, event_flags::pollin});
poller.add({from_handle, subscriber.handle()}, event_flags::pollin});

// This vector must be at least as large as the number of sockets being polled
vector<zmq::poller_event> events(2);
while (true) {
  size_t num_events = poller.wait_all(events, -1);
  // You may need to sleep a bit if num_events == 0

  for (int i = 0; i < num_events; i++) {
    zmq::message message;
    events[i].socket.recv(&message);
    ...
  } 
}

EDIT: Realized that the poller_event structure also contains a socket_ref! That makes things even easier!

With a stable zmq release, you need to #define ZMQ_BUILD_DRAFT_API to use poller_t and its bag.




回答2:


Q : Is it impossible to avoid hardcoding sockets in this case?

Yes.

This is the WHY part :

1 )
The API documented Poller-setup requires us to fill-in the pollitem_t item(s) into a mandatory data-structure the Poller-instance is expecting to receive from us. ( So this part is a MUST-HAVE one and there is no imaginable "avoidance"-trick possible here - opaque void* MUST be delivered to Poller so as to work as expected ... to indeed .poll() something ... )

2 )
A "reverse" transcoding ( hardcoded or not ) is not necessary ( thus there is not a thing to avoid here ), right due to the step 1 - your code already knows the "map" - it has generated the 1:1-map-of-pollitem_t item(s) for a mandatory delivery to the Poller under review.


EPILOGUE :

For cases, where the amount of the Socket-instances, that happen to be a subject to the initial building of the mandatory ( i.e. un-avoid-able ) 1:1-map-of-pollitem_t items data-structure ( which you started to call a "hardcoding" part ), one may design a scripted-tool for static cases ( for the case of known Socket-instances to be processed ) or an adaptive map-generator, that will consume your own managed pilot-"tape" ( your systematically maintained data-structure ) with all Socket-instances to be processed ).



来源:https://stackoverflow.com/questions/58639610/zeromq-how-to-cast-a-pollitem-t-item-used-in-poller-back-to-a-zeromq-socket

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!