[zeromq-dev] ZeroMQ integration with GLib main event loop

Thomas Rodgers rodgert at twrodgers.com
Thu Jul 27 23:46:04 CEST 2017


I don't know that this is any less complicated (and it's C++, not C), but
azmq integrates libzmq FD handling with Boost Asio's event loop, and that
can be 'manually' pumped by calling io_service::poll_one() from inside
another event dispatch loop.

https://github.com/zeromq/azmq


On Thu, Jul 27, 2017 at 9:37 AM Luca Boccassi <luca.boccassi at gmail.com>
wrote:

> glib is ridiculously complicated.
>
> When we had to use it what we did was creating a GIOChannel from the
> file descriptor (again this is from ZMQ_FD, not just the socket) with
> g_io_channel_unix_new, then creating a GSource from that with
> g_io_create_watch, then attaching the callback to the source with
> g_source_set_callback, and then finally attaching the source to the
> g_task with g_task_attach_source.
>
> This worked fine and we shipped a few releases using it.
>
> On Thu, 2017-07-27 at 17:03 +0300, Alexander Yanin wrote:
> > Hi,
> >
> > Thank you for the provided article. This article covers the main
> > approach
> > to integrating zmq fd into event loops more precisely than
> > stackoverflow
> > threads I've linked to my question. But it seems that there is still
> > no
> > answer to my question there, because my problem is in the very
> > beginning of
> > an integration process - I never get my IO_IN callback triggered :)
> > In other words, when I call `recv` method in a for loop directly, I
> > got
> > data, but when I connect zmq file descriptor to glib event loop to
> > listen
> > to IO_IN conditions, lambda function that handles such events is
> > never
> > called.
> > I've also tried connecting to other conditions than IO_IN, actually
> > to all
> > others (IO_ERR, IO_PRI, etc), but the result was the same except with
> > IO_OUT. IO_OUT condition triggers the callback, but writing to fd is
> > not my
> > case, as I am using ZMQ_SUB socket which is only for read purpose.
> >
> > 2017-07-27 15:55 GMT+03:00 Luca Boccassi <luca.boccassi at gmail.com>:
> >
> > > On Thu, 2017-07-27 at 15:02 +0300, Alexander Yanin wrote:
> > > > I am trying to integrate ZeroMQ into my Glib main event loop. As
> > > > I
> > > > have
> > > > seen on the official ZeroMQ FAQ and API reference and on some
> > > > stackoverflow
> > > > threads (zeromq glib main loop integration
> > > > <https://stackoverflow.com/questions/6695863/zeromq-glib-main-loo
> > > > p-in
> > > > tegration>
> > > > and How to use ZeroMQ in an GTK/QT/Clutter application?
> > > > <https://stackoverflow.com/questions/6452131/how-to-use-zeromq-in
> > > > -an-
> > > > gtk-qt-clutter-application>),
> > > > to do this I need to get ZeroMQ FD and then connect it to
> > > > existing
> > > > event
> > > > loop. But, unfortunately, In my case this does not work.
> > > >
> > > > here is the code:
> > > >
> > > > RefPtr<IOChannel> zmq_in;
> > > > zmq::context_t context (1);
> > > > zmq::socket_t subscriber (context, ZMQ_SUB);
> > > >
> > > > subscriber.connect("tcp://localhost:5556");const char *filter =
> > > > "10001 ";
> > > > subscriber.setsockopt(ZMQ_SUBSCRIBE, filter, strlen (filter));
> > > > const auto read_zmq = [this, &subscriber](Glib::IOCondition c) ->
> > > > bool {
> > > >     std::cout << " Received message on zmq!" << std::endl;
> > > >     int zipcode, temperature, relhumidity;
> > > >     zmq::message_t update;
> > > >     subscriber.recv(&update);
> > > >     std::istringstream iss(static_cast<char*>(update.data()));
> > > >     iss >> zipcode >> temperature >> relhumidity;
> > > >     std::cout << "Zipcode: " << zipcode << " Temperature: " <<
> > > > temperature
> > > >               << "Humidity: " << relhumidity;
> > > >     return true;};
> > > > for (int i = 0; i < 10 ; i++) {
> > > >     int zipcode, temperature, relhumidity;
> > > >     zmq::message_t update;
> > > >     subscriber.recv(&update);
> > > >     std::istringstream iss(static_cast<char*>(update.data()));
> > > >     iss >> zipcode >> temperature >> relhumidity;
> > > >     std::cout << "Zipcode: " << zipcode << "  Temperature: " <<
> > > > temperature
> > > >               << "  Humidity: " << relhumidity << std::endl;}
> > > > int fd = subscriber.getsockopt<int>(ZMQ_FD);
> > > > zmq_in = IOChannel::create_from_fd(fd);
> > > > Glib::signal_io().connect(read_zmq, zmq_in, Glib::IO_IN);
> > > >
> > > > What really happens when the code is executed: 10 messages are
> > > > successfully
> > > > received from Publisher (another process) in the for loop, but
> > > > when
> > > > it
> > > > comes to receiving messages from the Glib main event loop, my c++
> > > > lambda is
> > > > never called :(
> > > >
> > > > Here is the Publisher code in C almost completely taken from
> > > > ZeroMQ
> > > > Guide:
> > > >
> > > > #include <zmq.h>#include <stdio.h>#include <unistd.h>#include
> > > > <string.h>#include <assert.h>#include <stdlib.h>
> > > > int main (void){
> > > >         //  Prepare our context and publisher
> > > >         void *context = zmq_ctx_new ();
> > > >         void *publisher = zmq_socket (context, ZMQ_PUB);
> > > >         int rc = zmq_bind (publisher, "tcp://*:5556");
> > > >         assert (rc == 0);
> > > >
> > > >         //  Initialize random number generator
> > > >         while (1) {
> > > >                 //  Get values that will fool the boss
> > > >                 int zipcode, temperature, relhumidity;
> > > >                 zipcode     = rand () % 100000;
> > > >                 temperature = (rand () % 215) - 80;
> > > >                 relhumidity = (rand () % 50) + 10;
> > > >
> > > >                 //  Send message to all subscribers
> > > >                 char update [20];
> > > >                 sprintf (update, "%05d %d %d", zipcode,
> > > > temperature,
> > > > relhumidity);
> > > >                 zmq_send (publisher, update, 20, 0);
> > > >                 int ev;
> > > >                 size_t sizeof_ev = sizeof(ev);
> > > >         }
> > > >         zmq_close (publisher);
> > > >         zmq_ctx_destroy (context);
> > > >         return 0;}
> > > >
> > > > So where is the problem?
> > > >
> > > > P.S.:I am using glibmm c++ binding to Glib. My OS is Fedora 26.
> > > > My
> > > > ZeroMQ
> > > > version is 4.1.6
> > >
> > > Hi,
> > >
> > > I have no idea about that specific c++ glib binding, but as the
> > > answer
> > > on the first link you posted says you can't just poll a ZMQ socket,
> > > you
> > > need to get the file descriptor via the ZMQ_FD socket option and
> > > feed
> > > that to the poll, and then read in a loop as long as the ZMQ_EVENTS
> > > socket options returns ZMQ_POLLIN.
> > >
> > > This is because those FDs are edge triggered:
> > >
> > > https://funcptr.net/2012/09/10/zeromq---edge-triggered-notification
> > > /
> > >
> > > --
> > > Kind regards,
> > > Luca Boccassi
> > > _______________________________________________
> > > zeromq-dev mailing list
> > > zeromq-dev at lists.zeromq.org
> > > https://lists.zeromq.org/mailman/listinfo/zeromq-dev
> > >
> >
> > _______________________________________________
> > zeromq-dev mailing list
> > zeromq-dev at lists.zeromq.org
> > https://lists.zeromq.org/mailman/listinfo/zeromq-dev
>
> --
> Kind regards,
> Luca Boccassi_______________________________________________
> zeromq-dev mailing list
> zeromq-dev at lists.zeromq.org
> https://lists.zeromq.org/mailman/listinfo/zeromq-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.zeromq.org/pipermail/zeromq-dev/attachments/20170727/cdf6affa/attachment.htm>


More information about the zeromq-dev mailing list