2

How do i use ev_io with mqueues? I'm trying to do the following with no luck.

#include <fcntl.h>
#include <sys/stat.h>
#include <mqueue.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "ev.h"

#define MAX_Q_SIZE 255
#define MY_QUEUE "/test_queue"

typedef struct __test_ctxt_t
{
    ev_timer    timeout_watcher[32];
    ev_io       stdin_watcher;
    struct ev_loop *loop;
    mqd_t       mq;
    int         data;
}test_ctxt_t;

static test_ctxt_t *g_ctxt = NULL;

static void mq_callback(EV_P_ struct ev_io *w, int revents)
{
    test_ctxt_t *ctxt = (test_ctxt_t *)w;
    struct      mq_attr attr;
    char        msg[256];
    int         rcvd_msg_size;

    rcvd_msg_size = mq_receive(ctxt->mq, msg, MAX_Q_SIZE, NULL);
    if (rcvd_msg_size >= 0)
    {
        msg[rcvd_msg_size] = '\0';
        printf("Received: %s\n", msg);
        if (strcmp(msg, "stop") == 0)
        {
            printf("Exiting....\n");
            ev_unloop (EV_A_ EVUNLOOP_ONE);
        }
    }
}

static void timeout_cb1 (EV_P_ struct ev_timer *w, int revents)
{
  puts ("timeout timeout_cb1");
  //ev_unloop (EV_A_ EVUNLOOP_ONE);
}

static void timeout_cb2 (EV_P_ struct ev_timer *w, int revents)
{
  puts ("timeout timeout_cb2");
  //ev_unloop (EV_A_ EVUNLOOP_ONE);
}
static void timeout_cb3 (EV_P_ struct ev_timer *w, int revents)
{
  puts ("timeout timeout_cb3");
  //ev_unloop (EV_A_ EVUNLOOP_ONE);
}

int main (void)
{
    struct      mq_attr attr;

    g_ctxt = (test_ctxt_t *)calloc(1, sizeof(test_ctxt_t));

    g_ctxt->loop = ev_default_loop (0);

    /* initialize the queue attributes */
    attr.mq_flags = 0;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = 255;
    g_ctxt->mq = mq_open(MY_QUEUE, O_CREAT | O_RDONLY, 0644, &attr);
    if (g_ctxt->mq == -1)
    {
        printf("Unable to open Queue");
        return -1;
    }

    ev_io_init(&g_ctxt->stdin_watcher, mq_callback, g_ctxt->mq, EV_READ);
    ev_io_start(g_ctxt->loop, &g_ctxt->stdin_watcher);

    ev_timer_init (&g_ctxt->timeout_watcher[0], timeout_cb1, 10, 0.);
    ev_timer_start (g_ctxt->loop, &g_ctxt->timeout_watcher[0]);

    ev_loop (g_ctxt->loop, 0);

    return 0;
}

I'm able to get the timer call back but io callback is never called on sending a messsage to the queue. Is it possible to use POSIX mqueue with libev ?

Duck
  • 26,924
  • 5
  • 64
  • 92
  • I don't see why this wouldn't work on linux but I didn't have the patience to install ev_io to test it. It seems like the lib just wraps `select` or `poll`, both of which work with mqd_t (just file desc) in linux. OP, what OS are you on? – Duck Oct 29 '13 at 19:27
  • 1
    Here : http://stackoverflow.com/questions/10045015/why-is-there-no-poll-select-like-mechanism-for-message-queue it specifies that on Linux select/poll can be used with mqs. However it is not portable. – O.C. Oct 30 '13 at 04:52
  • Agree with @O.C. - Linux message queues are file descriptors and therefore they can be used in libev IO watchers. This is unfortunately non-portable approach. – Ales Teska Jun 18 '17 at 10:33

1 Answers1

0

There are basically three ways, how to do that:

1) On Linux platform, the message queue handler is a valid file descriptor.

Polling message queue descriptors

On Linux, a message queue descriptor is actually a file descriptor, and can be monitored using select(2), poll(2), or epoll(7). This is not portable.

From mq_overview man page

You can utilize ev_io watcher to listen for incoming messages.

This is LINUX specific and non-portable code.

2) You can use function mq_notify to configure a signal that will be send whenever then message queue receives a new message. This signal can be handled by a ev_signal watcher from libev.

This seems to be more portable code but due to a signal interaction, the performance will be a bit lower.

See mq_notify man page.

3) Switch to datagram-oriented sockets, UNIX or network. These offer the roughly equal ability to send a message (aka datagram). You will get connectionless, best effort delivery, unreliable, message delivery service.

This approach is very portable.

Macintosh note:
There is no POSIX message queue implementation in macOS so the portability of such a code is limited in regards to this Apple platform. There is a possibility to mimic the same function on NSOperationQueue or Grand Central Dispatch but it will certainly result in a extensive amount of the work.

Ales Teska
  • 1,198
  • 1
  • 17
  • 38