Ericsson / xcm

The Extensible Connection-oriented Messaging (XCM) library.
BSD 3-Clause "New" or "Revised" License
15 stars 4 forks source link

Allow interrupting blocking send and receive #68

Open m-ronnblom opened 2 years ago

m-ronnblom commented 2 years ago

For applications that use multi-threading for concurrency, combined with blocking XCM sockets, it would be useful to be able to wake up a thread blocking in a send or receive operation.

For such applications today, they need to implement this kind of functionality themselves. Such a "interruptable" xcm_receive(), for example, could be built by using a wrapper around the real xcm_receive(), use a non-blocking XCM socket, and block in the application itself using e.g. select(). In addition to waiting for the XCM fd, the select fdset should also include a "wake up" fd of some sort (e.g., a pipe). When the thread need to be awaken, some other thread writes to this fd.

This is fairly straight-forward, but it could be worth including this into the library itself. Most of the mechanics is already there, since XCM uses non-blocking fds everywhere internally. Having a "wake up" fd per default might be too costly, so it's probably better to add a "xcm.interruptable" flag which is set, to enable this functionality. A new API call is also need, to do the actual interruption. Careful consideration should be made, for the semantics, to avoid races. What happens if you attempt to interrupt a thread which at the time of the call just unblocked?

Would it be useful to be able to interrupt a blocking xcm_connect() as well? It's not obvious how that would be possible, though, since there is not yet a socket pointer for the application to use.

m-ronnblom commented 1 year ago

One possibility: add a new socket attribute "xcm.interruptible" with an integer value, which may be passed to all socket-creating functions. This would also work for xcm_connect().

If this attribute is provided, the socket may be "unblocked", and the user-specified "interruption domain id" is the value of the attribute.

"xcm.interruptible" would be paired with a new API function xcm_interrupt(int64_t id). This function would unblock all blocking function calls on all threads and all sockets, where "xcm.interruptable" == id. Any new calls would also immediately return, in the same manner.

A function xcm_uninterrupt() would restore the situation to that it was before.

"Interrupt" is a little misleading since it may lead the user to think it's related to either signals (which it is not), or hardware interrupts (which it is also not). "xcm.unblockable"? Sounds strange.