Your problem is, that you are calling glXSwapBuffers between two calls of xcb_poll_for_event. Therefore you only can handle one message per screen refresh.
Apart from your multithreading solution you could simply process events until xcb_poll_for_event would return zero. When you are finished with handling all pending events, you could return to rendering.