blob: 7726e167cb554c8534b8932392c19eb3f9258aa4 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.20"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Qpid Proton C++ API: Multithreading</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function() { init_search(); });
/* @license-end */
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">Qpid Proton C++ API
&#160;<span id="projectnumber">0.32.0</span>
</div>
</td>
<td> <div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<img id="MSearchSelect" src="search/mag_sel.svg"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
alt=""/>
<input type="text" id="MSearchField" value="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.svg" alt=""/></a>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.20 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search');
/* @license-end */
</script>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function(){initNavTree('mt_page.html',''); initResizable(); });
/* @license-end */
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div class="PageDoc"><div class="header">
<div class="headertitle">
<div class="title">Multithreading </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p><a class="anchor" id="md__tmp_rgemmell_transom_qpid-proton-0"></a>.32.0_cpp_docs_mt</p>
<p>Full multithreading support is available with C++11 and later. Limited multithreading is possible with older versions of C++. See the last section of this page for more information.</p>
<p><code><a class="el" href="classproton_1_1container.html" title="A top-level container of connections, sessions, and links.">proton::container</a></code> handles multiple connections concurrently in a thread pool, created using <code><a class="el" href="classproton_1_1container.html#a13a43e6d814de94978c515cb084873b1" title="Run the container in the current thread.">proton::container::run()</a></code>. As AMQP events occur on a connection the container calls <code><a class="el" href="classproton_1_1messaging__handler.html" title="Handler for Proton messaging events.">proton::messaging_handler</a></code> event callbacks. The calls for each connection are <em>serialized</em> - callbacks for the same connection are never made concurrently.</p>
<p>You assign a handler to a connection in <code><a class="el" href="classproton_1_1container.html#a32d867e171bce707cc73c7003ec489db" title="Connect using the default Connection Configuration file.">proton::container::connect()</a></code> or <code><a class="el" href="classproton_1_1listen__handler.html#a3f8b8dc9641dc3a3ed19e2a60ec8eccc" title="Called for each accepted connection.">proton::listen_handler::on_accept()</a></code> with <code><a class="el" href="classproton_1_1connection__options.html#a7bca23aeb3455378ef2d35975758e504" title="Set a connection handler.">proton::connection_options::handler()</a></code>. We recommend you create a separate handler for each connection. That means the handler doesn't need locks or other synchronization to protect it against concurrent use by Proton threads. If you use the handler concurrently from non-Proton threads then you will need synchronization.</p>
<p>The examples <a class="el" href="multithreaded_client_8cpp-example.html">multithreaded_client.cpp</a> and <a class="el" href="multithreaded_client_flow_control_8cpp-example.html">multithreaded_client_flow_control.cpp</a> illustrate these points.</p>
<h1><a class="anchor" id="autotoc_md4"></a>
Thread-safety rules</h1>
<p><code><a class="el" href="classproton_1_1container.html" title="A top-level container of connections, sessions, and links.">proton::container</a></code> is thread-safe <em>with C++11 or greater</em>. An application thread can open (or listen for) new connections at any time. The container uses threads that call <code><a class="el" href="classproton_1_1container.html#a13a43e6d814de94978c515cb084873b1" title="Run the container in the current thread.">proton::container::run()</a></code> to handle network IO and call user-defined <code><a class="el" href="classproton_1_1messaging__handler.html" title="Handler for Proton messaging events.">proton::messaging_handler</a></code> callbacks.</p>
<p><code><a class="el" href="classproton_1_1container.html" title="A top-level container of connections, sessions, and links.">proton::container</a></code> ensures that calls to event callbacks for each connection instance are <em>serialized</em> (not called concurrently), but callbacks for different connections can be safely executed in parallel.</p>
<p><code><a class="el" href="classproton_1_1connection.html" title="A connection to a remote AMQP peer.">proton::connection</a></code> and related objects (<code><a class="el" href="classproton_1_1session.html" title="A container of senders and receivers.">proton::session</a></code>, <code><a class="el" href="classproton_1_1sender.html" title="A channel for sending messages.">proton::sender</a></code>, <code><a class="el" href="classproton_1_1receiver.html" title="A channel for receiving messages.">proton::receiver</a></code>, <code><a class="el" href="classproton_1_1delivery.html" title="A received message.">proton::delivery</a></code>) are <em>not</em> thread-safe and are subject to the following rules.</p>
<ol type="1">
<li>They can only be used from a <code><a class="el" href="classproton_1_1messaging__handler.html" title="Handler for Proton messaging events.">proton::messaging_handler</a></code> event callback called by Proton or a <code><a class="el" href="classproton_1_1work__queue.html" title="Unsettled API - A context for thread-safe execution of work.">proton::work_queue</a></code> function (more below).</li>
<li>You cannot use objects belonging to one connection from a callback for another connection. We recommend a single handler instance per connection to avoid confusion.</li>
<li>You can store Proton objects in member variables for use in a later callback, provided you respect rule two.</li>
</ol>
<p><code><a class="el" href="classproton_1_1message.html" title="An AMQP message.">proton::message</a></code> is a value type with the same threading constraints as a standard C++ built-in type. It cannot be concurrently modified.</p>
<h1><a class="anchor" id="autotoc_md5"></a>
Work queues</h1>
<p><code><a class="el" href="classproton_1_1work__queue.html" title="Unsettled API - A context for thread-safe execution of work.">proton::work_queue</a></code> provides a safe way to communicate between different connection handlers or between non-Proton threads and connection handlers.</p>
<ul>
<li>Each connection has an associated <code><a class="el" href="classproton_1_1work__queue.html" title="Unsettled API - A context for thread-safe execution of work.">proton::work_queue</a></code>.</li>
<li>The work queue is thread-safe (C++11 or greater). Any thread can add <em>work</em>.</li>
<li><em>Work</em> is a <code>std::function</code>, and bound arguments will be called like an event callback.</li>
</ul>
<p>When the work function is called by Proton, it will be serialized safely so that you can treat the work function like an event callback and safely access the handler and Proton objects stored on it.</p>
<p>The examples <a class="el" href="multithreaded_client_8cpp-example.html">multithreaded_client.cpp</a> and <a class="el" href="multithreaded_client_flow_control_8cpp-example.html">multithreaded_client_flow_control.cpp</a> show how you can send and receive messages from non-Proton threads using work queues.</p>
<h1><a class="anchor" id="autotoc_md6"></a>
The wake primitive</h1>
<p><code><a class="el" href="classproton_1_1connection.html#a473371542eaeba6f67660582fe6a6074" title="Unsettled API - Trigger an event from another thread.">proton::connection::wake()</a></code> allows any thread to "wake up" a connection by generating an <code>on_connection_wake()</code> callback. This is the <em>only</em> thread-safe <code><a class="el" href="classproton_1_1connection.html" title="A connection to a remote AMQP peer.">proton::connection</a></code> function.</p>
<p>This is a lightweight, low-level primitive for signaling between threads.</p>
<ul>
<li>It does not carry any code or data (unlike <code><a class="el" href="classproton_1_1work__queue.html" title="Unsettled API - A context for thread-safe execution of work.">proton::work_queue</a></code>).</li>
<li>Multiple calls to <code>wake()</code> can be "coalesced" into a single <code>on_connection_wake()</code>.</li>
<li>Calls to <code>on_connection_wake()</code> can occur without any call to <code>connection::wake()</code>. Proton uses wake internally.</li>
</ul>
<p>The semantics of <code>wake()</code> are similar to <code>std::condition_variable::notify_one</code>. There will be a wakeup, but there must be some shared application state to determine why the wakeup occurred and what, if anything, to do about it.</p>
<p>Work queues are easier to use in many instances, but <code>wake()</code> may be useful if you already have your own external thread-safe queues and just need an efficient way to wake a connection to check them for data.</p>
<h1><a class="anchor" id="autotoc_md7"></a>
Using older versions of C++</h1>
<p>Before C++11 there was no standard support for threading in C++. You can use Proton with threads but with the following limitations.</p>
<ul>
<li>The container will not create threads, it will only use the single thread that calls <code><a class="el" href="classproton_1_1container.html#a13a43e6d814de94978c515cb084873b1" title="Run the container in the current thread.">proton::container::run()</a></code>.</li>
<li>None of the Proton library classes are thread-safe, including <code><a class="el" href="classproton_1_1container.html" title="A top-level container of connections, sessions, and links.">proton::container</a></code> and <code><a class="el" href="classproton_1_1work__queue.html" title="Unsettled API - A context for thread-safe execution of work.">proton::work_queue</a></code>. You need an external lock to use <code><a class="el" href="classproton_1_1container.html" title="A top-level container of connections, sessions, and links.">proton::container</a></code> in multiple threads.</li>
</ul>
<p>The only exception is <code><a class="el" href="classproton_1_1connection.html#a473371542eaeba6f67660582fe6a6074" title="Unsettled API - Trigger an event from another thread.">proton::connection::wake()</a></code>, it <em>is</em> thread-safe even in older C++.</p>
<p>You can implement your own <code><a class="el" href="classproton_1_1container.html" title="A top-level container of connections, sessions, and links.">proton::container</a></code> using your own threading library, or ignore the container and embed the lower-level <code><a class="el" href="classproton_1_1io_1_1connection__driver.html" title="Unsettled API - An AMQP driver for a single connection.">proton::io::connection_driver</a></code> in an external poller. These approaches still use the same <code><a class="el" href="classproton_1_1messaging__handler.html" title="Handler for Proton messaging events.">proton::messaging_handler</a></code> callbacks, so you can reuse most of your application code. Note that this is an advanced undertaking. There are a few pointers in <a class="el" href="io_page.html">IO integration</a>.</p>
</div></div><!-- contents -->
</div><!-- PageDoc -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated by <a href="http://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.8.20 </li>
</ul>
</div>
</body>
</html>