Add ability to execute notification on specific thread
gelldur opened this issue · 12 comments
Eg. someone want to execute notification in background thread
this feature is expected,espacially for AsyncEventBus.
the the consume() function is expected to be put into one background thread to process the event asynchronously.
the backgound thread may be like the following:
std::thread t( {
while (true)
{
getAsyncBus()->consume();
// using namespace std::chrono_literals;
// std::this_thread::sleep_for(1s);
}
});
t.detach();
but the consume() will lead the CPU load to 100% without some sleep. if you added some sleep, the event may not be consumed in time.
will you make the function consume() blocked if there is no event?
Yes sure. It could be done.
@shenfumin I'm going to add: (brief example)
if(bus.wait())
{
bus.consume();
}
So it will wait until event come in. Also can be waitFor(10s)
as timeout
thanks your information. it is good idea, i agree with you.
Are there any updates to this? I noticed AsyncEventBus
has been removed (but AsyncEventBusPerformance.cpp
added in the same commit??), but I can not see an alternative mechanism for consuming events asynchronously (and calling the listeners on different threads).
Hello
For now there is no possibility to handle event per thread. As EventBus 3.0 you may only handle events on specific thread calling EventBus::process()
but you shouldn't call process from same bus on different threads, you should pick one and stick to it.
So you can add events from any thread as this is thread safe operation but processing events (calling listeners) is done on thread which is calling EventBus::process()
Currently I'm not planning to add such feature out of the box. Maybe you can add new "perk" to bus and decide on some tag that you pass on which thread process event.
Other solution may be to create MAIN EventBus which will pass event to other EventBus2 which will work on desired thread.
If you have any suggestions I'm happy to discuss.
Are there any updates to this? I noticed
AsyncEventBus
has been removed (butAsyncEventBusPerformance.cpp
added in the same commit??), but I can not see an alternative mechanism for consuming events asynchronously (and calling the listeners on different threads).
the most code had been changed, but the old version may be suite for you. you can checkout the old version for this issue
commit d51be92632576224f8976996dc02cfcae157fe61
Author: Dawid Drozd <drozddawid.uam@gmail.com>
Date: Mon Jun 24 19:10:01 2019 +0200
Add AsyncEventBus::wait() function
then you can setup one thread to consume events asynchronously like the following
std::thread t( {
while (true)
{
getAsyncBus()->wait()
getAsyncBus()->consume();
}
});
t.detach();
In the absence of a proper event loop in c++ having a secondary listen-only event bus that is thread-specific. the main issue is that the execution of the event listener must run in the thread it was allocated. Maybe there can be a thread-aware listener that implicitly creates its own "listen-only" bus.
@gelldur actually isn't this was PassEverythingPerk
would more or less do? You would create a bus on each thread, and then use the perk to forward everything to it? I guess the only issue there would be the removal of that when the thread exits. Or do I misunderstand what that does? Maybe it needs some more documentation ;)
@geiseri yes you are right that was intention of PassEverythingPerk
to have for example 2 event loops e.g. for logic and UI and pass events between those EventBus. I nned to prepare use case for such scenario. I'm also not so happy of such solution right now :) but we will see.
EventListener
will be executed on thread which calls EventBus::process()
it doesn't matter on which thread we create it. (It is thread safe)
I think I have a use case here, but it seems to be not working. I will try to put something in wandbox.
To be honest I think the best way is to have a thread-specific bus that is a subordinate of the main bus. Chances are that the thread might have a different scheduler or even event loop that would want to drive the bus. Since the bus itself is thread-safe everyone would publish back to the main one. I think the only issue you might run into is backpressure if a subordinate cant keep up. You wouldn't want to block the main bus, so you might need to introduce a TTL, or something.
My current case is that I have a main thread that needs to asynchronously communicate with an IO system that runs in a different thread. I need to be able to alert the main thread listeners when a message arrives, but I also need to send messages back. Since neither can block the other the bus seems the best option. Originally I was going to have a bus for rx and a bus for tx. The problem there is that the IO is in a thread pool, and coordination pretty much nullifies any decoupling the bus has to offer.
If each thread in the thread pool had its own subordinate bus that would solve this in a pretty slick way.
EventListener
will be executed on thread which callsEventBus::process()
it doesn't matter on which thread we create it. (It is thread safe)
The only reason I would want the thread-specific ownership would be to make it explicit it was tied to that thread. Since calling process from the wrong thread can cause interesting things to happen it would be nicer to the API consumer to make that hard to do =)