Skip to content

Message Ownership

Paul N Stickney edited this page Feb 1, 2020 · 34 revisions

Message Lifetime

Messages in VT are allocated off-stack and have internally managed reference counts. As such, they must be handled correctly to avoid memory leaks. The MsgPtr (in 1.0 this is named MsgSharedPtr) type acts a a shared-ref wrapper to ensure proper lifetime management.

Note: The method of message creation is currently under some updates. The original method uses makeSharedMessage which returns a MsgT*. VT takes ownership of the messages these raw pointers represent in send and broadcast calls. A message is created with makeSharedMessage MUST either be guaranteed to be passed to VT for transmission or wrapped inside a MsgPtr.

Good (1.0):

M* msg = makeSharedMessage<M>(..);
theMsg->sendMsg(dest, msg);

theMsg->sendMsg(dest, makeSharedMessage<M>(..));

MsgPtr<M> msg = makeMessage<M>(..);
theMsg->sendMsg(dest, msg.get()) // MsgPtr<M>.get() -> M*

theMsg->sendMsg(dest, makeMessage<M>(..).get())

Bad (1.0):

// Message is leaked when it is not supplied to sendMsg.
// Only create messages as they are immediately going to be used.
M* msg = makeSharedMessage<M>(..);
if (maybe_send) {
    theMsg->sendMsg(dest, msg);
}

Send-once

Messages in VT can be sent at most once. It is an error if the same message is sent multiple times.

Messages received from send/broadcast callbacks are considered sent and cannot be directly sent again. A new message must be constructed.

Invalid code:

T* msg = makeSharedMessage<T>(..);
theMsg()->sendMsg(dest, msg);
// Invalid: message has already been sent
theMsg()->sendMsg(dest, msg);

T* msg = makeSharedMessage<T>(..);
theMsg()->sendMsg(dest, msg, [](T* cb_message) {
  // Invalid: messages from callbacks cannot be re-sent.
  theMsg()->sendMsg(dest, cb_message);
});

1.1 Proposal: Active message supports a Copy Constructor that resets the transmission state of the new message such that the following is valid:

T* msg = makeSharedMessage<T>(..);
theMsg()->sendMsg(dest, msg, [](T* cb_message) {
  // Valid: a copy of the message without transmission state is created and sent
  theMsg()->sendMsg(dest, makeSharedMessage(*cb_message));
});

Messages in Callbacks

Callbacks are given a Msg* value once a message is received. The lifetime of message is only for the duration of the callback. If the message needs to extend beyond the callback lifetime, wrap it inside a MsgPtr. For 1.0 this is done using promoteMsg(rawMsgTPtr) which returns a MsgPtr<MsgT>.