Sophie

Sophie

distrib > Mageia > 6 > i586 > by-pkgid > f93881942bd3805980c2fe63aa853d78 > files > 272

qtdoc5-5.9.4-1.mga6.noarch.rpm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- threads.qdoc -->
  <title>Reentrancy and Thread-Safety | Qt 5.9</title>
  <link rel="stylesheet" type="text/css" href="style/offline-simple.css" />
  <script type="text/javascript">
    document.getElementsByTagName("link").item(0).setAttribute("href", "style/offline.css");
    // loading style sheet breaks anchors that were jumped to before
    // so force jumping to anchor again
    setTimeout(function() {
        var anchor = location.hash;
        // need to jump to different anchor first (e.g. none)
        location.hash = "#";
        setTimeout(function() {
            location.hash = anchor;
        }, 0);
    }, 0);
  </script>
</head>
<body>
<div class="header" id="qtdocheader">
  <div class="main">
    <div class="main-rounded">
      <div class="navigationbar">
        <table><tr>
<td ><a href="index.html">Qt 5.9</a></td><td >Reentrancy and Thread-Safety</td></tr></table><table class="buildversion"><tr>
<td id="buildversion" width="100%" align="right">Qt 5.9.4 Reference Documentation</td>
        </tr></table>
      </div>
    </div>
<div class="content">
<div class="line">
<div class="content mainContent">
  <link rel="prev" href="threads-synchronizing.html" />
  <link rel="next" href="threads-qobject.html" />
<p class="naviNextPrevious headerNavi">
<a class="prevPage" href="threads-synchronizing.html">Synchronizing Threads</a>
<span class="naviSeparator">  &#9702;  </span>
<a class="nextPage" href="threads-qobject.html">Threads and QObjects</a>
</p><p/>
<div class="sidebar">
<div class="toc">
<h3><a name="toc">Contents</a></h3>
<ul>
<li class="level1"><a href="#reentrancy">Reentrancy</a></li>
<li class="level1"><a href="#thread-safety">Thread-Safety</a></li>
<li class="level1"><a href="#notes-on-qt-classes">Notes on Qt Classes</a></li>
</ul>
</div>
<div class="sidebar-content" id="sidebar-content"></div></div>
<h1 class="title">Reentrancy and Thread-Safety</h1>
<span class="subtitle"></span>
<!-- $$$threads-reentrancy.html-description -->
<div class="descr"> <a name="details"></a>
<p>Throughout the documentation, the terms <i>reentrant</i> and <i>thread-safe</i> are used to mark classes and functions to indicate how they can be used in multithread applications:</p>
<ul>
<li>A <i>thread-safe</i> function can be called simultaneously from multiple threads, even when the invocations use shared data, because all references to the shared data are serialized.</li>
<li>A <i>reentrant</i> function can also be called simultaneously from multiple threads, but only if each invocation uses its own data.</li>
</ul>
<p>Hence, a <i>thread-safe</i> function is always <i>reentrant</i>, but a <i>reentrant</i> function is not always <i>thread-safe</i>.</p>
<p>By extension, a class is said to be <i>reentrant</i> if its member functions can be called safely from multiple threads, as long as each thread uses a <i>different</i> instance of the class. The class is <i>thread-safe</i> if its member functions can be called safely from multiple threads, even if all the threads use the <i>same</i> instance of the class.</p>
<p><b>Note: </b>Qt classes are only documented as <i>thread-safe</i> if they are intended to be used by multiple threads. If a function is not marked as thread-safe or reentrant, it should not be used from different threads. If a class is not marked as thread-safe or reentrant then a specific instance of that class should not be accessed from different threads.</p><a name="reentrancy"></a>
<h2 id="reentrancy">Reentrancy</h2>
<p>C++ classes are often reentrant, simply because they only access their own member data. Any thread can call a member function on an instance of a reentrant class, as long as no other thread can call a member function on the <i>same</i> instance of the class at the same time. For example, the <code>Counter</code> class below is reentrant:</p>
<pre class="cpp">

  <span class="keyword">class</span> Counter
  {
  <span class="keyword">public</span>:
      Counter() { n <span class="operator">=</span> <span class="number">0</span>; }

      <span class="type">void</span> increment() { <span class="operator">+</span><span class="operator">+</span>n; }
      <span class="type">void</span> decrement() { <span class="operator">-</span><span class="operator">-</span>n; }
      <span class="type">int</span> value() <span class="keyword">const</span> { <span class="keyword">return</span> n; }

  <span class="keyword">private</span>:
      <span class="type">int</span> n;
  };

</pre>
<p>The class isn't thread-safe, because if multiple threads try to modify the data member <code>n</code>, the result is undefined. This is because the <code>++</code> and <code>--</code> operators aren't always atomic. Indeed, they usually expand to three machine instructions:</p>
<ol class="1" type="1"><li>Load the variable's value in a register.</li>
<li>Increment or decrement the register's value.</li>
<li>Store the register's value back into main memory.</li>
</ol>
<p>If thread A and thread B load the variable's old value simultaneously, increment their register, and store it back, they end up overwriting each other, and the variable is incremented only once!</p>
<a name="thread-safety"></a>
<h2 id="thread-safety">Thread-Safety</h2>
<p>Clearly, the access must be serialized: Thread A must perform steps 1, 2, 3 without interruption (atomically) before thread B can perform the same steps; or vice versa. An easy way to make the class thread-safe is to protect all access to the data members with a QMutex:</p>
<pre class="cpp">

  <span class="keyword">class</span> Counter
  {
  <span class="keyword">public</span>:
      Counter() { n <span class="operator">=</span> <span class="number">0</span>; }

      <span class="type">void</span> increment() { <span class="type">QMutexLocker</span> locker(<span class="operator">&amp;</span>mutex); <span class="operator">+</span><span class="operator">+</span>n; }
      <span class="type">void</span> decrement() { <span class="type">QMutexLocker</span> locker(<span class="operator">&amp;</span>mutex); <span class="operator">-</span><span class="operator">-</span>n; }
      <span class="type">int</span> value() <span class="keyword">const</span> { <span class="type">QMutexLocker</span> locker(<span class="operator">&amp;</span>mutex); <span class="keyword">return</span> n; }

  <span class="keyword">private</span>:
      <span class="keyword">mutable</span> <span class="type">QMutex</span> mutex;
      <span class="type">int</span> n;
  };

</pre>
<p>The QMutexLocker class automatically locks the mutex in its constructor and unlocks it when the destructor is invoked, at the end of the function. Locking the mutex ensures that access from different threads will be serialized. The <code>mutex</code> data member is declared with the <code>mutable</code> qualifier because we need to lock and unlock the mutex in <code>value()</code>, which is a const function.</p>
<a name="notes-on-qt-classes"></a>
<h2 id="notes-on-qt-classes">Notes on Qt Classes</h2>
<p>Many Qt classes are <i>reentrant</i>, but they are not made <i>thread-safe</i>, because making them thread-safe would incur the extra overhead of repeatedly locking and unlocking a QMutex. For example, QString is reentrant but not thread-safe. You can safely access <i>different</i> instances of QString from multiple threads simultaneously, but you can't safely access the <i>same</i> instance of QString from multiple threads simultaneously (unless you protect the accesses yourself with a QMutex).</p>
<p>Some Qt classes and functions are thread-safe. These are mainly the thread-related classes (e.g&#x2e; QMutex) and fundamental functions (e.g&#x2e; QCoreApplication::postEvent()).</p>
<p><b>Note: </b>Terminology in the multithreading domain isn't entirely standardized. POSIX uses definitions of reentrant and thread-safe that are somewhat different for its C APIs. When using other object-oriented C++ class libraries with Qt, be sure the definitions are understood.</p></div>
<!-- @@@threads-reentrancy.html -->
<p class="naviNextPrevious footerNavi">
<a class="prevPage" href="threads-synchronizing.html">Synchronizing Threads</a>
<span class="naviSeparator">  &#9702;  </span>
<a class="nextPage" href="threads-qobject.html">Threads and QObjects</a>
</p>
        </div>
       </div>
   </div>
   </div>
</div>
<div class="footer">
   <p>
   <acronym title="Copyright">&copy;</acronym> 2017 The Qt Company Ltd.
   Documentation contributions included herein are the copyrights of
   their respective owners.<br>    The documentation provided herein is licensed under the terms of the    <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation    License version 1.3</a> as published by the Free Software Foundation.<br>    Qt and respective logos are trademarks of The Qt Company Ltd.     in Finland and/or other countries worldwide. All other trademarks are property
   of their respective owners. </p>
</div>
</body>
</html>