[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [Libevent-users] event base: multi-thread producers, single thread consumer?



On Fri, Apr 22, 2011 at 11:43 AM, Nick Mathewson <nickm@xxxxxxxxxxxxx> wrote:
On Thu, Apr 21, 2011 at 6:29 PM, Scott Dorr <j.scott.dorr@xxxxxxxxx> wrote:
> I've got a server with multiple threads, each with their own event base.
>  Works wonderfully.  I have a new situation that would be solved quite
> easily if I could have all threads (but one) push events onto the event base
> for the final thread.  That final thread will process events as they come
> up.
> Reading through some of the additional libevent documentation, I'm wondering
> if I'm going to need to engage the various locking bits
> (evthread_set_id_callback, evthread_set_lock_callbacks, etc) to preserve the
> sanctity of that one event base?

Probably.  If you want to do anything that affects an event_base from
multiple threads (and this includes touching events that are
associated with an event_base), you need to enable locking before you
do anything else with libevent, or construct any event_bases.

Most people don't want to call the "evthread_set_*_callback()"
functions on their own: evthread_use_windows_threads() and
evthread_use_pthreads() are what you'll probably want, unless you need
to interface with an existing locking library that isn't one of those.

Yeah, after posting my question, I continued to do a bit of digging and came to the conclusion that probably all I'd need was evthread_use_pthreads() -- the other, more manual, evthread*callback() functions were in place in case you didn't use one of the already supported thread libraries (eg. pthreads).
 

> So far, I've been able to avoid any kind of locking in this server and would
> be quite reluctant to add any at this point.

Well, if you want to communicate between threads without any locking,
you can't use changes to Libevent data structures to do it: Libevent's
data structures are only safe to access from multiple concurrent
threads if locking is enabled.

You might be able to achieve what you want by some other means, like
using pipe() or socketpair() to create a communications channel
between threads.  Have the thread that receives all the information
listen for EV_READ on the pipe/socketpair, and have other threads use
write to send it information.  You'd either need to give each sending
thread its own pipe to write on, or you'd need to figure out a way to
prevent messages from getting mixed up -- maybe by using one-byte
messages, or datagram-based socketpairs, or some such.

For now, I'll stick with the locking. :(  It's really only to handle an edge-condition that will rarely ever happen, so the chance of serializing behind a lock is greatly mitigated.  I'll probably convert to some kind of pipe()/socketpair() solution when I've got more time to work on efficiency updates for edge cases. ;)

Thanks for the response!

- scott