我如何中断xcb_wait_for_event?

时间:2015-05-22 01:47:14

标签: c++ multithreading xcb

在一个单独的线程(std::thread)中,我有一个等待xcb_wait_for_event的事件循环。当程序退出时,我想通过中断很好地关闭(我有一个设置线程局部变量的解决方案,并且循环中的检查点抛出一个异常),然后将我的事件线程加入到main中线。问题是xcb_wait_for_event;我需要一种从早期返回的方法,或者我需要替代函数。

有人可以提出解决方案吗?谢谢你的帮助!

2 个答案:

答案 0 :(得分:2)

我相信我已经找到了合适的解决方案。我已使用以下功能替换xcb_wait_for_event

xcb_generic_event_t *WaitForEvent(xcb_connection_t *XConnection)
{
    xcb_generic_event_t *Event = nullptr;

    int XCBFileDescriptor = xcb_get_file_descriptor(XConnection);
    fd_set FileDescriptors;

    struct timespec Timeout = { 0, 250000000 }; // Check for interruptions every 0.25 seconds

    while (true)
    {
        interruptible<std::thread>::check();

        FD_ZERO(&FileDescriptors);
        FD_SET(XCBFileDescriptor, &FileDescriptors);

        if (pselect(XCBFileDescriptor + 1, &FileDescriptors, nullptr, nullptr, &Timeout, nullptr) > 0)
        {
            if ((Event = xcb_poll_for_event(XConnection)))
                break;
        }
    }

    interruptible<std::thread>::check();

    return Event;
}

利用xcb_get_file_descriptor,我可以使用pselect等待有新事件,或者直到发生指定的超时。这种方法导致额外的CPU成本可以忽略不计,保持在0.0%的平面上(在这个i7上)。唯一的缺点是#34;必须等待最多0.25秒以检查是否有中断,并且我确定可以安全地降低限制。

答案 1 :(得分:1)

一种更整洁的方法是做这样的事情(代码片段是从我当前正在处理的某些代码中提取的):

void QXcbEventQueue::sendCloseConnectionEvent() const {
    // A hack to close XCB connection. Apparently XCB does not have any APIs for this?
    xcb_client_message_event_t event;
    memset(&event, 0, sizeof(event));

    event.response_type = XCB_CLIENT_MESSAGE;
    event.format = 32;
    event.sequence = 0;
    event.window = m_connection->clientLeader();
    event.type = m_connection->atom(QXcbAtom::_QT_CLOSE_CONNECTION);
    event.data.data32[0] = 0;

    xcb_connection_t *c = m_connection->xcb_connection();
    xcb_send_event(c, false, m_connection->clientLeader(),
                   XCB_EVENT_MASK_NO_EVENT, reinterpret_cast<const char *>(&event));
    xcb_flush(c); }

对于_QT_CLOSE_CONNECTION,请使用您自己的原子来表示退出,在我的情况下,clientLeader()是一些不可见的窗口,该窗口始终存在于我的X11连接中。如果您没有任何可重复使用的不可见窗口,请创建一个:)

使用此方法,您可以在看到此特殊事件到达时以xcb_wait_for_event终止线程。