如何最好地中断zeroMQ轮询方法以进行清理和终止

时间:2014-01-24 11:12:45

标签: c++ multithreading zeromq

用C ++编写我有一个线程,它使用zmq poll方法来发现何时有新事件要处理,哪个工作正常。我想要的是这个线程退出,同时在没有更多事件预期时很好地清理。

而不是无限循环我可以在那里放置一个条件,但它需要REQUEST_TIMEOUT_MS才能到达那里。所以我的问题是,为程序退出中断轮询的最佳方法是什么?

void * Requester::recieve_thread(void *arg) {

    zmq::socket_t * soc = (zmq::socket_t *) arg;

    zmq::pollitem_t items[] = { { *soc, 0, ZMQ_POLLIN, 0 } };

    while (1) {
        zmq::poll(&items[0], 1, REQUEST_TIMEOUT_MS);

        if (items[0].revents & ZMQ_POLLIN) {

            // process the event
        }
    }

    // clean up
}

2 个答案:

答案 0 :(得分:4)

经常提到你可以破坏zmq上下文,并且共享该上下文的任何内容都会退出,但是这会产生一场噩梦,因为这将删除套接字对象,并且你的退出代码必须尽力避免死亡的雷区指针。

尝试关闭套接字不起作用,因为它们不是线程安全的,你最终会崩溃。

答案:最好的方法是按照ZeroMQ指南建议通过多线程进行任何使用;使用zmq套接字而不是线程互斥/锁/等。

Requester::Requester(zmq::context_t* context)
{
    m_context = context;

    // Create a socket that you'll use as the interrupt-event receiver
    // I'm using a random address and an inproc socket (inprocs need to share a context)
    snprintf(m_signalStopAddr, sizeof(m_signalStopAddr) / sizeof(*m_signalStopAddr), "inproc://%lx%x", (unsigned long)this, rand());
    m_signalStop = new zmq::socket_t(m_context, ZMQ_PAIR);
    m_signalStop->bind(m_signalStopAddr);
}

// Your thread-safe poll interrupter
Requester::interrupt()
{
    char dummy;
    zmq::socket_t doSignal(m_context, ZMQ_PAIR);
    doSignal.connect(m_signalStopAddr);
    doSignal.send(&dummy, sizeof(dummy));
}

void * Requester::recieve_thread(void *arg)
{
    zmq::socket_t * soc = (zmq::socket_t *) arg;
    zmq::pollitem_t items[] =
    {
        { *soc, 0, ZMQ_POLLIN, 0 },
        { *m_signalStop, 0, ZMQ_POLLIN, 0 }
    };

    while (1)
    {
        zmq::poll(items, 2, REQUEST_TIMEOUT_MS);
        if (items[1].revents & ZMQ_POLLIN)
        {
            break; // exit
        }

        if (items[0].revents & ZMQ_POLLIN)
        {
            // process the event
        }
    }

    // Cleanup
}

zmq::context_t* m_context;
zmq::socket_t* m_signalStop; // Don't forget to delete this!
char m_signalStopAddr[100];

答案 1 :(得分:1)

不要中断轮询 - 向线程发送指示其清理并退出的消息。