Tony -<br><br>Thanks, that really helps.<br><br>- Jim<br><br>Jim Irrer <a href="mailto:irrer@umich.edu">irrer@umich.edu</a> (734) 647-4409<br>University of Michigan Hospital Radiation Oncology<br>519 W. William St. Ann Arbor, MI 48103<br>
<br><br><div class="gmail_quote">---------- Forwarded message ----------<br>From: <b class="gmail_sendername">Tony Garnock-Jones</b> <span dir="ltr"><<a href="mailto:tonyg@lshift.net">tonyg@lshift.net</a>></span><br>
Date: Thu, Jul 1, 2010 at 8:39 PM<br>Subject: Re: C client and thread safety<br>To: Jim Irrer <<a href="mailto:irrer@umich.edu">irrer@umich.edu</a>><br>Cc: rabbitmq-discuss <<a href="mailto:rabbitmq-discuss@lists.rabbitmq.com">rabbitmq-discuss@lists.rabbitmq.com</a>><br>
<br><br>Hi Jim,<br>
<div class="im"><br>
Jim Irrer wrote:<br>
> I'm working with the RabbitMQ C client, and had a few questions<br>
> about thread safety.<br>
<br>
</div>In general, there is no thread awareness built in to librabbitmq at all. It is<br>
currently the responsibility of applications using the library to ensure that<br>
multiple threads don't screw up the library's state.<br>
<br>
That said, there is no longer any global state at all in the library, so if you<br>
stick to one connection (and thus one socket) per thread, you should be fine.<br>
<div class="im"><br>
> Must a socket returned by amqp_open_socket be exclusively<br>
> associated with one connection, or can it be used for multiple<br>
> connections?<br>
<br>
</div>One connection. Each AMQP connection needs exactly one socket to communicate over.<br>
<div class="im"><br>
> Must a socket returned by amqp_open_socket be exclusively<br>
> used by one thread, or can it be used by multiple threads?<br>
<br>
</div>The connection associated with the socket must be used by one thread *at a<br>
time*. The locking can get quite complicated when you take into account the way<br>
librabbitmq currently deals with incoming events, so sticking with one<br>
connection for each thread makes life much easier.<br>
<div class="im"><br>
> Must a connection returned by amqp_new_connection be exclusively<br>
> used to read from or write to one channel/queue, or is using multiple ok,<br>
> even in a multi-threaded environment.<br>
<br>
</div>Multiple are OK, but again, each connection is best kept to a single thread.<br>
Think of multiple channels as separate *transaction* and *error reporting*<br>
contexts; they don't buy much else in current versions of the AMQP protocol :-)<br>
<div class="im"><br>
> If any of these can be used by multiple threads, is there a performance<br>
> advantage in reusing the same socket or connection, or is using multiple<br>
> ones better?<br>
<br>
</div>Using a single connection with multiple channels means that TCPs<br>
congestion-avoidance counts all AMQP traffic as a single stream, whereas using<br>
multiple connections with a single channel each means that TCP will count each<br>
stream separately. Which is more appropriate to your application depends on the<br>
structure of your network: the former might be more appropriate for a WAN link,<br>
the latter for a LAN or a datacentre, etc.<br>
<div class="im"><br>
> It looks like channels (created with amqp_channel_open) are identified<br>
> by (small?)<br>
> integers chosen by the application and are associated with the<br>
> connection. This<br>
> means that it is the responsibility of the application to choose unique<br>
> numbers,<br>
> properly close them, etc.. It would seem cleaner to pass a connection as a<br>
> single parameter to amqp_channel_open and have it return a pointer to a<br>
> channel,<br>
> and the list of channels would be maintained in the connection.<br>
<br>
</div>Yes, there is a lot of per-channel state management the library currently<br>
doesn't do. A set of "active" channel numbers might not be too hard to manage.<br>
<div class="im"><br>
> Also, it looks like amqp_new_connection uses 'calloc' to allocate<br>
> memory for a connection, but amqp_connection_close does not do<br>
> a 'free' to avoid the memory leak. Maybe that was intentional, but if<br>
> not it should be changed.<br>
<br>
</div>The amqp_connection_close() function causes an AMQP Connection.Close RPC to<br>
happen on the open socket, but does not then tear down any of the application<br>
state: that's what amqp_destroy_connection() is for. The relevant pairings are<br>
roughly<br>
<br>
For local connection state management (calloc/free):<br>
amqp_new_connection<br>
amqp_destroy_connection<br>
<br>
For remote connection state management (Connection.Open/Tune/Close, once local<br>
connection state exists):<br>
amqp_login<br>
amqp_connection_close<br>
...plus interactions required on receipt of a Connection.Close method frame<br>
from the peer.<br>
<br>
Cheers,<br>
<font color="#888888"> Tony<br>
<br>
</font></div><br>