-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
libxcb is just a wrapper around a socket with some external state, so theoretically we should be able to implement CanBeAsyncDisplay on XcbDisplay (and also XlibDisplay). In practice, it ends up being more complicated.
Here are the methods of CanBeAsyncDisplay in order of difficulty of implementation:
try_wait_for_reply_raw,try_wait_for_event- Trivial. Usexcb_poll_for_reply64orxcb_poll_for_event, and returnAsyncStatus::Readif one doesn't come up.try_send_request_raw- Hard.libxcbon its own does not support non-blocking writes. However, it is possible to get the file descriptor of the connection, preform non-blocking writes on that, and then usexcb_writevto update the connection's sequence number. Note that this restrictsasyncsupport to being Unix-only, since Windows async systems use Windows sockets.try_flush- Hard.xcb_flushpreforms a blocking flush of the internal connection buffer, and there is no other way to access that buffer from the external API. That being said, while using the async API, we probably won't involve the internal buffer too much. We could have a check saying, "if the socket has been taken since we last used it, this flush will be blocking", and then also make sure to flush our own buffer. Note that this means that we'd have to make our own buffer for writes here, which I expected to have to do anyways.format_request- Very Hard. We need the sequence number to do formatting, which we get fromxcb_take_socket(note that we need to callxcb_take_socketfor writing above). First, it preforms a flush of the internal buffer which, as discussed above, can be problematic. Although that can be avoided, we do have to deal with the case where a malicious user takes the socket and passes in a callback that blocks for an extended period of time. We could probably also check to see if the socket has been taken and, if so, expect to block. That being said, we also may need to query for extensions and maximum request length, which use internal consistent state and can't be done without blocking. In these cases, this moves up to Impossible.try_check_for_error- Very Hard. Basically the same as flushing and then reading.try_generate_xid,try_maximum_request_length- Impossible.xcb_generate_idandxcb_maximum_request_lengthrely on internal state that needs to be kept consistent betweenbreadxandlibxcb. Even if we could get around this by emulating it on thebreadxend, foreign code could call these functions before/after theDisplayin instantiated and mess up our state.
The Impossibles are generally cold operations, so we could probably eat the cost of using a threadpool and import blocking or using tokio's spawn_blocking function. The Hards require a new type at minimum to wrap XcbDisplay, and probably some kind of system for taking the XCB socket.
Metadata
Metadata
Assignees
Labels
No labels