Hi All,
Hopefully a quick question:
Say I have a thread waiting on an event with (eg) chEvtWaitAny().
An event occurs and the thread starts to do some work.
If another event occurs while the thread is still working, what is the expected outcome?
Will the event be dropped?
Thanks
New event behaviour while busy
- Giovanni
- Site Admin
- Posts: 14565
- Joined: Wed May 27, 2009 8:48 am
- Location: Salerno, Italy
- Has thanked: 1112 times
- Been thanked: 937 times
- Contact:
Re: New event behaviour while busy
Hi,
The event is buffered, as soon the thread re-enters chEvtWaitAny() it will be immediately served.
The only scenario where an event is "lost" is when an event is broadcasted twice while the thread is executing, only one is buffered. Note that this is by design, it is the same event so one notification is sufficient.
Giovanni
The event is buffered, as soon the thread re-enters chEvtWaitAny() it will be immediately served.
The only scenario where an event is "lost" is when an event is broadcasted twice while the thread is executing, only one is buffered. Note that this is by design, it is the same event so one notification is sufficient.
Giovanni
Re: New event behaviour while busy
Hi again Giovanni,
If from my event worker thread I need to register a new event, is it acceptable to simply call chEvtBroadcastFlags from the worker thread?
My worker thread has a condition where say event_1 is registered from an external source.
The worker thread processes event_1, but determines that there is more event_1 related work to do.
I don't want to simply sit in a loop and check if that particular worker has more to do. I want to register an event, so that any other unrelated event might also be processed.
A code example of what I think I want:
A code example of what I don't want:
Do you have any thoughts on this?
Thank
If from my event worker thread I need to register a new event, is it acceptable to simply call chEvtBroadcastFlags from the worker thread?
My worker thread has a condition where say event_1 is registered from an external source.
The worker thread processes event_1, but determines that there is more event_1 related work to do.
I don't want to simply sit in a loop and check if that particular worker has more to do. I want to register an event, so that any other unrelated event might also be processed.
A code example of what I think I want:
Code: Select all
while(1) {
chEvtWaitAny(EVENT_MASK(0));
eventflags_t flags = chEvtGetAndClearFlags(&listener);
if (flags & event_1) {
if (do_event_1_work() == true) {
// More event_1 work to do
chEvtBroadcastFlags(&event_source, (eventflags_t)event_1);
}
}
if (flags & event_2) {
// process event_2, etc etc
}
}
A code example of what I don't want:
Code: Select all
while(1) {
chEvtWaitAny(EVENT_MASK(0));
eventflags_t flags = chEvtGetAndClearFlags(&listener);
if (flags & event_1) {
bool more_work = false;
do {
more_work = do_event_1_work();
} while (more_work == true);
}
if (flags & event_2) {
// process event_2, etc etc
}
}
Do you have any thoughts on this?
Thank
- FXCoder
- Posts: 393
- Joined: Sun Jun 12, 2016 4:10 am
- Location: Sydney, Australia
- Has thanked: 184 times
- Been thanked: 131 times
Re: New event behaviour while busy
Hi,
Unless you need to notify other subscriber threads (if any) listening to the event source, then simply use a direct thread add to post your "more to do" event.
Then your code can process other events flags (if any) and then pickup the newly posted event flag at the top of the loop.
See...
--
Bob
Unless you need to notify other subscriber threads (if any) listening to the event source, then simply use a direct thread add to post your "more to do" event.
Then your code can process other events flags (if any) and then pickup the newly posted event flag at the top of the loop.
See...
Code: Select all
chEvtAddEvents(events)
--
Bob
Re: New event behaviour while busy
Hi again,
On further investigation, chEvtAddEvents(events) would add an event.
I also need to broadcast a flag for the event.
Can you offer any advice on how to do that too?
I could reach into the event_listener struct and OR the flags myself. Would this be considered an acceptable Chibios way of doing things?!
It seems a bit hacky to me!
Thanks again
On further investigation, chEvtAddEvents(events) would add an event.
I also need to broadcast a flag for the event.
Can you offer any advice on how to do that too?
I could reach into the event_listener struct and OR the flags myself. Would this be considered an acceptable Chibios way of doing things?!
It seems a bit hacky to me!
Code: Select all
while(1) {
chEvtWaitAny(EVENT_MASK(0));
eventflags_t flags = chEvtGetAndClearFlags(&listener);
if (flags & event_1) {
if (do_event_1_work() == true) {
// More event_1 work to do
listener.flags |= (eventflags_t)event_1;
chEvtAddEvents(EVENT_MASK(0));
}
}
if (flags & event_2) {
// process event_2, etc etc
}
}
Thanks again
- FXCoder
- Posts: 393
- Joined: Sun Jun 12, 2016 4:10 am
- Location: Sydney, Australia
- Has thanked: 184 times
- Been thanked: 131 times
Re: New event behaviour while busy
OK. The terminology may be a little confusing.
What the worker thread gets is a flag set in its own thread bitmask.
There is no need to do more than that.
However, if you need other subscribers to get the event then just use the broadcast API (as you originally described).
You'll need the event source object address available to your worker thread to do that of course (a global or an API to get the address as part of your system).
Then when you broadcast to that event source all subscribers (including the worker_1 which initiated the broadcast) will get the event added to their thread event flags.
--
Bob
What the worker thread gets is a flag set in its own thread bitmask.
There is no need to do more than that.
However, if you need other subscribers to get the event then just use the broadcast API (as you originally described).
You'll need the event source object address available to your worker thread to do that of course (a global or an API to get the address as part of your system).
Then when you broadcast to that event source all subscribers (including the worker_1 which initiated the broadcast) will get the event added to their thread event flags.
--
Bob
Re: New event behaviour while busy
Hey,
Yeah, I'm a bit confused.
I see how calling chEvtAddEvents would add a new event and allow chEvtWaitAny to continue.
What I don't understand is how would I get back into the "event_1" flag condition?
chEvtGetAndClearFlags would have got and cleared the flags, so on the next entry to chEvtGetAndClearFlags after calling chEvtAddEvents, the "event_1" flag bit would not be set?
If I dig into chEvtAddEvents I can see that it just ORs the current thread epending with the event passed into it. No flags are set in there.
Also, hello from Australia!
Yeah, I'm a bit confused.
I see how calling chEvtAddEvents would add a new event and allow chEvtWaitAny to continue.
What I don't understand is how would I get back into the "event_1" flag condition?
chEvtGetAndClearFlags would have got and cleared the flags, so on the next entry to chEvtGetAndClearFlags after calling chEvtAddEvents, the "event_1" flag bit would not be set?
If I dig into chEvtAddEvents I can see that it just ORs the current thread epending with the event passed into it. No flags are set in there.
Also, hello from Australia!
- FXCoder
- Posts: 393
- Joined: Sun Jun 12, 2016 4:10 am
- Location: Sydney, Australia
- Has thanked: 184 times
- Been thanked: 131 times
Re: New event behaviour while busy
Hi,
In this case (where you want to re-post events) put chEvtGetAndClearEvents(...) at the top to get the events in your thread and then chEvtGetAndClearFlags(...) at the bottom of the loop to clear the listener object flags.
This would leave any added thread flags set by the worker_1 (etc.), as part of the loop work intact, but will clear the event listener flags at the bottom.
Of course you will still be in a somewhat hard loop doing it this way but at least servicing the worker list in a round robin fashion as they post "more to do".
--
Bob
In this case (where you want to re-post events) put chEvtGetAndClearEvents(...) at the top to get the events in your thread and then chEvtGetAndClearFlags(...) at the bottom of the loop to clear the listener object flags.
This would leave any added thread flags set by the worker_1 (etc.), as part of the loop work intact, but will clear the event listener flags at the bottom.
Of course you will still be in a somewhat hard loop doing it this way but at least servicing the worker list in a round robin fashion as they post "more to do".
--
Bob
Who is online
Users browsing this forum: No registered users and 14 guests