Dispatching single EventQueue using multiple Threads fails when EventQueue size is larger than number of dispatching Threads

Hello,

I have run into a problem with event dispatching.

For our devices we use a thread pool which enables asynchronous programming. For that, we’ve implemented Threads that are all dispatching the same underlying EventQueue.

It works well if the number of Threads does not exceed the number of events per EventQueue. However, if the number of Events is larger, only a single Thread keeps dispatching the remaining Events even if the other threads have also finished.

Example of how dispatching fails:
#Threads 3
#Events 6

When running the program, i get the following output:

Event 1 is dispatched in Thread 1
Event 2 is dispatched in Thread 2
Event 3 is dispatched in Thread 3
Event 1 finished, Thread 1 idles
Event 4 is dispatched in Thread 1
Event 2 finished, Thread 2 idles
Event 3 finished, Thread 3 idles
Event 5 is dispatched in Thread 1
Event 6 is dispatched in Thread 1

Is that expected behavior? I would expected sth similar to:

Event 1 is dispatched in Thread 1
Event 2 is dispatched in Thread 2
Event 3 is dispatched in Thread 3
Event 1 finished, Thread 1 idles
Event 4 is dispatched in Thread 1
Event 2 finished, Thread 2 idles
Event 5 is dispatched in Thread 2
Event 3 finished, Thread 3 idles
Event 6 is dispatched in Thread 3

Thanks for your help.

Andy

Hi @horeich,

Mbed Os event queue dispatch method is only safe to use concurrently if no ms are provided in the argument list (immediate dispatch). How dispatching is made depends on several factor; thread scheduling being the most important one and that might well be what you are observing here.

This kind of work-stealing pattern are not encouraged on Mbed for several reasons: Processing of an event may start earlier but it doesn’t mean it will finish earlier because the RTOS has to divide CPU time across threads. Furthermore this pattern doesn’t work well with APIs that are not thread safe as multiple threads can blindly access the same context. That is the case for many Mbed Os connectivity technologies for instance.

It might be interesting that you detail what you want to achieve so we can advise you a more suited pattern. You mentioned asynchronous programing but asynchronicity can be achieved with a single thread of execution too and event/work queue are corner stones of this paradigm.

Hi @vcoubard,

Thank you for your clarifications.

In the stated example I’m only using immediate dispatch

Work-stealing seems to be the keyword here. The queue is probably locked in a single thread event processing loop which does not allow any other threads that have finished their work.

Meanwhile I programmed my own dispatch loop that works this way (deploying a thread pool/ queue and an event queue):

  • event is posted on queue
  • if thread isa idle thread in the pool, queue is called on that thread
  • if thread has finished, it is queued in the thread pool again and tries to dispatch the next event

Using both, thread queue and event queue helps to avoid a work stealing pattern while using a single disptach loop. Also allows for variable thread priority. Access to the queues must be synched, of course. Works well so far