Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support returning a status from an async port as an alternate queue full behavior #555

Open
celskeggs opened this issue Dec 13, 2024 · 7 comments
Labels
proposed feature A proposed new feature

Comments

@celskeggs
Copy link

Currently there is no easy way for the sender of a message on an async port to observe whether the queue is full.

Let's look at adding a queue full behavior that returns a status instead of either dropping or invoking a behavior on the receiver. For example, OK if the message was successfully placed on the queue, and DROPPED if the message was dropped.

@bocchino bocchino added the proposed feature A proposed new feature label Dec 13, 2024
@bocchino
Copy link
Collaborator

@timcanham @LeStarch This seems like a good idea to me. Thoughts?

@bocchino
Copy link
Collaborator

I'm not sure this would be a specified queue full behavior at the receiver end. I think it would be a change to the port invocation interface. Any port type that does not have a return value in the FPP model (and so could be used in an asynchronous context) would have an implicit status return. Invoking the port would cause the status to be produced. If the port is connected to a sync port at the other end, it would always return OK. But if the port at the other end is async, it could return something else like QUEUE_FULL.

@celskeggs
Copy link
Author

I don't think you want to impact every output port that doesn't return a value. You'd either end up with lots of code sprinkled with FW_ASSERT(status == OK); or you'd end up with lots of code that simply ignores the status returned by a port, simply because there are many uses for synchronous ports without return values. It would introduce many opportunities for error if a port written to assume a synchronous input port (that always returns OK) was connected to an asynchronous input port (that might not always return OK).

Here's an alternative proposal: you could have a particular return type for a port that can be used in an asynchronous context.

port BufferTrySend(ref buf: Fw.Buffer) -> Status

# Example in a component that wants to asynchronously implement the interface:
async input port try_send: BufferTrySend

# The declaration:
void try_send_handler(FwIndexType portNum, Fw::Buffer &buf) override;

# Example in a component that wants to synchronously implement the interface:
sync input port try send: BufferTrySend

# The declaration:
Status try_send_handler(FwIndexType portNum, Fw::Buffer &buf) override;

This would not require a major change to how we handle port calls without return values in general. It would just open the door to returning a status from one particular kind of async port. This status would be returned by the autocoded port implementation when it enqueues or fails to enqueue the message.

@bocchino
Copy link
Collaborator

bocchino commented Dec 13, 2024

It might be OK to require a check or a cast to void. The cast to void would be not because the output port is assumed to be connected to a sync input port, but because there's nothing to do on the sender end if the message is dropped.

If we wanted to be more rigorous in the model, we could allow an output port instance P to specify that it must be connected to a sync input port; in this case the code generator would omit the status return for the port invocation function for P. However, this would limit the contexts in which the output port could be used.

If an output port P has port type T, and T returns data, then we know that P cannot be connected to an async input port. Otherwise I don't think we should use the port type T to determine whether the output invocation function for P returns a status. The status return depends on the kind of connection (sync or async) and not on the port type. Also, it's a common pattern to use the same port type in different contexts (sync and async) in different components.

@bocchino
Copy link
Collaborator

Also, the status is not the return type of the input port handler -- an async input handler never gets called unless the message went through the queue, and it always has return type void. The status is the return type of the function that's called to invoke the output port, on the thread of the sending component.

@celskeggs
Copy link
Author

I think we're talking past each other. Let's schedule a meeting to discuss this.

@bocchino
Copy link
Collaborator

Sounds good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposed feature A proposed new feature
Projects
None yet
Development

No branches or pull requests

2 participants