Optimal multithread model

Christophe Meessen christophe at meessen.net
Tue Mar 16 15:24:32 CET 2010


Hello,

sorry to have woken the thread troll. It sounds like a very passionate 
discussion topic.

My rationale is to favor code simplicity and clarity at the cost of some 
potential performance penalty. This led me to the leader/follower 
pattern with worker threads handling each request independently.

I was considering using libev as a portable replacement of epoll or 
kevent which would straightforwardly do the job, but apparently it isn't 
as simple.


Marc Lehmann a écrit :

> I would experiment by simply handing the event loop to the next
> thread in each callback, and acquiring the loop back once finished
> (stopping/starting of watchers is required here).
>   
I'm not sure I understood this correctly. Do you mean I should put the 
leader/follower polka inside the callback ? This implies the different 
worker threads call the ev_loop, but just when all the others are 
inactive, and then in the callback, just synchronize themselves so that 
only one thread returns from the callback.

I don't understand how this can work because we end up with multiple 
threads executing the ev_loop. This doesn't seem safe because the 
threads may have context information on their stack on the current 
ev_loop function which may become incoherent. Did I misunderstood your 
proposal ?

> That way your callbacks would compete for the event loop, and the event
> loop would only poll once all current callbacks have been invoked - before
> each (or each slow) callback, the event loop would be passed to the next
> thread.
>   
Isn't that the same as calling ev_loop with the ONE_SHOT flag ?


Here is an optimized version of the previous skeleton code in which I 
now use the follower and leader keywords where they belong. I expect 
this to be a better use of the ev_loop(ONE_SHOT).
notify() is only called when the leader thread leaves the ev_loop loop 
and is about to process a request.

worker_thread_function(...)
{
     while( !done )
     {
           // follower thread pool
           follower_count++;
           while( has_leader_thread )
                wait_follower_notification();  // done with a condition 
variable
           follower_count--;

           // leader thread task
           if( !done )
           {
               has_leader_thread  = true;
               do ev_loop( ONE_SHOT );
               while( (!has_pending_requests() ||  follower_count == 0) 
&& !done )
               has_leader_thread = false;
           }
           notify_follower();

           // process pending requests in parallel
           while( has_pending_requests() )
               process_request(); 
    }
}




More information about the libev mailing list