Module callback

Source
Expand description

§Generic Callbacks

When sending cross-process messages, we sometimes want to run custom callbacks when the recipient has finished processing. The callback should run in the sender’s address space, and could be something like enqueuing a task. In Multi-process mode we can implement this by providing an IpcSender to the recipient, which the recipient can use to send some data back to the senders process. To avoid blocking the sender, we can pass the callback to the ROUTER, which runs the callback when receiving the Ipc message. The callback will be run on every reply message from the recipient. IpcSenders are also Cloneable, so the Router will sequentialise callbacks.

§Callback scenario visualization

The following visualization showcases how Ipc and the router thread are currently used to run callbacks asynchronously on the sender process. The recipient may keep the ReplySender alive and send an arbitrary amount of messages / replies.

              Process A                      |              Process B
                                             |
+---------+   IPC: SendMessage(ReplySender)  |          +-------------+  clone  +-------------+
| Sender  |-------------------------------------------> |  Recipient  | ------> | ReplySender |
+---------+                                  |          +-------------+         +-------------+
  |                                          |                 |                       |
  | RegisterCallback A  +---------+          |  Send Reply 1   |        Send Reply 2   |
  + ------------------> | Router  | <--------------------------+-----------------------+
                        +---------+          |
                            | A(reply1)      |
                            | A(reply2)      |
                            |     ...        |
                            v                |
                                             |

§Optimizing single-process mode.

In Single-process mode, there is no need for the Recipient to send an IpcReply, since they are in the same address space and could just execute the callback directly. Since we want to create an abstraction over such callbacks, we need to consider constraints that the existing multiprocess Ipc solution imposes on us:

  • Support for FnMut callbacks (internal mutable state + multiple calls)
  • The abstraction should be Cloneable

These constraints motivate the GenericCallback type, which supports FnMut callbacks and is clonable. This requires wrapping the callback with Arc<Mutex<>>, which also adds synchronization, which could be something that existing callbacks rely on.

§Future work

  • Further abstractions for callbacks with fewer constraints, e.g. callbacks which don’t need to be cloned by the recipient, or non-mutable callbacks.
  • A tracing option to measure callback runtime and identify callbacks which misbehave (block) for a long time.

Structs§

GenericCallback
A mechanism to run a callback in the process this callback was constructed in.
GenericCallbackVisitor 🔒

Enums§

GenericCallbackVariants 🔒

Type Aliases§

MsgCallback
The callback type of our messages.