Skip to content

xcb_poll_for_event causes 100% usage of one cpu core

I’m learning c and messing around with xcb lib (instead of X11) on a raspberry pi4. The problem is that when implementing the events loop with xcb_poll_for_event instead of xcb_wait_for_event, one core of four is 100% full. What am I doing wrong? And is there any benefit of using wait_for_event (blocking way) instead of xcb_poll_for_event(non blocking)? The goal is to create a window where the user interact with keyboard/mouse/gamepad on objects, like a game. Can anyone give a hand? The relevant code is:

int window_loop_test(xcb_connection_t *connection, Display *display){
      /* window loop non blocked waiting for events */
      int running = 1;
      while (running) {
          xcb_generic_event_t *event = xcb_poll_for_event(connection);
          if (event) {
              switch (event->response_type & ~0x80) {
              case XCB_EXPOSE: {
                  // TODO
              case XCB_KEY_PRESS: {
                  /* Quit on 'q' key press */
                  /* write key pressed on console */
                  const xcb_key_press_event_t *press =
                      (xcb_key_press_event_t *)event;
                  XKeyEvent keyev;
                  keyev.display = display;
                  keyev.keycode = press->detail;
                  keyev.state = press->state;
                  char key[32];
                  XLookupString(&keyev, key, sizeof(key) - 1, NULL, NULL);
                  // key[len] = 0;
                  printf("Key pressed: %sn", key);
                  printf("Mod state: %dn", keyev.state);
                  if (*key == 'q')
                      running = 0;
      return 0;



Polling and waiting each have their advantages and are good for different situations. Neither is “wrong” per se, but you need to use the correct one for your specific use case.

xcb_wait_for_event(connection) is a blocking call. The call will not return until an event is available, and the return value is is that event (unless an error occurs). It is good for situations where you only want the thread to respond to events, but otherwise not do anything. In that case, there is no need to spend CPU resources when no events are coming in.

xcb_poll_for_event(connection) is a non-blocking call. The call always returns immediately, but the result will be NULL if no event is available. It is good for situations where you want the thread to be able to do useful work even if no events are coming in. As you found out, it’s not good if the thread only needs to respond to events, as it can consume CPU resources unnecessarily.

You mention that your goal is to create a game or something similar. Given that there are many ways to architect a game, either function can be suitable. But there are a couple of basic things to keep in mind that will determine which function you want to use. There may be other considerations as well, but this will give you an idea of what to look out for.

First of all, is your input system running on the same thread as other systems (simulation, rendering, etc)? If so, it’s probably important to keep that thread available for work other than waiting for input events. In this case, xcb_poll_for_event() is almost required, otherwise your thread will be blocked until an event comes in. However, if your input system is on its own thread that doesn’t block your other threads, it may be acceptable to use xcb_wait_for_event() and let that thread sleep when no events are coming in.

The second consideration is how quickly you need to respond to input events. There’s often a delay in waking up a thread, so if fast response times are important you’ll want to avoid letting the thread sleep in the first place. Again, xcb_poll_for_event() will be your friend in this case. If response times are not critical, xcb_wait_for_events() is an option.