-
Notifications
You must be signed in to change notification settings - Fork 7.3k
zbus: ZBUS_WAITER_DEFINE
#88690
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
base: main
Are you sure you want to change the base?
zbus: ZBUS_WAITER_DEFINE
#88690
Conversation
Add a new type of observer that simply gives a semaphore when a channel is published to. This can simplify code that wants to deal with zbus channel data sequentially. Signed-off-by: Jordan Yates <[email protected]>
Add a helper macro to declare a waiter observer on the stack for use with `zbus_chan_add_obs`. Signed-off-by: Jordan Yates <[email protected]>
Add tests for observers of type `ZBUS_OBSERVER_WAITER_TYPE`. Signed-off-by: Jordan Yates <[email protected]>
Validate that an observer created with `ZBUS_RUNTIME_WAITER_DEFINE` operates correctly. Signed-off-by: Jordan Yates <[email protected]>
d3638ae
to
361d0eb
Compare
@JordanYates, please describe the addition more. Please follow this format #88499 What is the issue this feature is solving? Why is this important for the community? |
Additional information added to the PR. |
|
@JordanYates, The first alternative is already good enough. static K_SEM_DEFINE(chan_published, 0, 1);
static void callback1(const struct zbus_channel *chan)
{
k_sem_give(&chan_published);
}
ZBUS_LISTENER_DEFINE(lis1, callback1); I don't see the benefit in adding another type of observer just for that use case. Another benefit of your alternative is that you can reuse the same listener for all the semaphores of your system, like: static K_SEM_DEFINE(chan1_published, 0, 1);
static K_SEM_DEFINE(chan2_published, 0, 1);
static K_SEM_DEFINE(chan3_published, 0, 1);
static K_SEM_DEFINE(chan4_published, 0, 1);
static void callback1(const struct zbus_channel *chan)
{
if(chan == &chan1) {
k_sem_give(&chan1_published);
} else if(chan == &chan2) {
k_sem_give(&chan2_published);
} else if(chan == &chan3) {
k_sem_give(&chan3_published);
} else if(chan == &chan4) {
k_sem_give(&chan4_published);
}
}
ZBUS_LISTENER_DEFINE(lis_waiter, callback1); With just one listener, you can address the need you're pointing out without adding more complexity to zbus. I strongly suggest not adding the feature. |
The use case of natively giving the primary Zephyr synchronization object with the minimum boilerplate?
Which you then can't enable or disable on a per channel basis.
The complexity of this?
I don't see the difference between this and #88499, it is already possible to achieve that functionality without adding more complexity to zbus as well. Why is a callback with |
Again, you are trying to add something that breaks consistency. The first was the runtime observer. Maybe you don't care about it, but I do. People started asking me about what a "zbus_observer_node" is. Now I need to explain that, not you. I mean usage and maintenance complexity. The more variability we have, the steeper the learning curve for new developers is, and the higher the maintenance cost. All observers can observe more than one channel and behave the same. Zbus executes the listeners implicitly and notifies subscribers, so they need to call Thus, with your addition, we have a type of observer that:
These are unaligned with zbus. Regarding the #88499, that is perfectly aligned with the current zbus way. Everyone who already uses a listener will be able to use that. With a bit of change (adding "ASYNC" to the definition), they can exchange between a Another clear alternative to your feature suggestion is to use a subscriber with just one element in the queue: ZBUS_SUBSCRIBER_DEFINE(sub1, 1) If you need something to use in the Lastly, I suggest you change the feature to align with zbus or remove the PR. |
I assume that you are referring to #84271. At no point was the problem of "consistency" raised, my reading was that people agreed that internal use of Now you are criticizing me for working through your feedback over the course of several months and getting the PR to the point of approval and merging? If the contribution was as worthless as you seem to feel it was, open a revert PR and get others to agree with you. I apologize for attempting to improve your subsystem. |
Did you forget the whole discussion #79777? I pointed out several times that the change would affect the way the observers work. I mentioned "inconsistencies" and "break compatibility". I was against that. However, when you created the new PR (#84271), I was exhausted and in a tough moment in my life. I was tired of discussing it, so I gave up and accepted it, which I regret. I apologise to the community for letting it be added without more debate.
A changing (not reverse) PR is on the way. The feature is essential, but the implementation did not consider the side effects.
It's not mine, you know that. However, as a maintainer, I will strive to make it the best, most consistent, and healthiest as possible. |
About this PR, I still think this has more cons than pros. Please, adjust that to be more consistent with the current zbus way. |
I did not. You observed that the original proposal would break the ability to register the same observer against multiple channels. That was true, and I reworked the PR to fix that limitation. There was no change, I don't understand your argument here. If you call
This is sufficiently vague to be useless. If we are just going to argue back and forth about the utility of giving a semaphore directly instead of needing to write a callback, this will never go anywhere since you have the final say. Unless you have concrete requests, I don't see the point. A semaphore will always be a semaphore, and do the things a semaphore does. It you dislike the idea of semaphores being supported in zbus, there is nothing more I can do to change how a semaphore behaves. Regardless, my response to the various "this is not aligned with zbus" points:
This observer is exactly the same, it can "wait" on as many channels as the user desires.
While observing a single channel is the simplest case (as is also true for listeners and subscribers), there is nothing stopping it being used on multiple channels. There are use-cases where it does not matter which channel was published to (e.g. triggering a state-machine iteration).
That's the definition, no argument there
"listener" and "subscriber" were unfamiliar names (in the zbus context) until zbus came into being as well. |
What do you think of calling that static K_SEM_DEFINE(sem_chan_published, 0, 1);
ZBUS_SEM_SUBSCRIBER_DEFINE(waiter, &sem_chan_published); To make that clear. Listeners are observers whose actions are known at the time of publication, since subscribers are asynchronous and do not state their actions at the time of publication. So, you are adding a different kind of subscriber. Sounds good to you? @JordanYates |
Add a new type of observer that can be used to wait on a channel until data is published.
Is your enhancement proposal related to a problem? Please describe.
Waiting until new data is published on a channel currently requires polling in a loop or defining an observer of a different type that gives a semaphore in a dedicated callback. This is verbose for such a simple use case.
Describe the solution you'd like
This PR
Describe alternatives you've considered
Static observers can use this pattern.
Which is more verbose than:
Runtime observers don't have a clear alternative, as there is no easy way to map the semaphore handle into the callback.