1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="highlight.min.css">
<script src="highlight.min.js"></script><script>
hljs.configure({languages: ['cpp']});
hljs.highlightAll();
</script><title>Chapter 29. Multi-threaded programs</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
<link rel="home" href="index.html" title="Programming with gtkmm 4">
<link rel="up" href="index.html" title="Programming with gtkmm 4">
<link rel="prev" href="sec-custom-css-names.html" title="Custom CSS Names">
<link rel="next" href="sec-using-glib-dispatcher.html" title="Using Glib::Dispatcher">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr><th colspan="3" align="center">Chapter 29. Multi-threaded programs</th></tr>
<tr>
<td width="20%" align="left">
<a accesskey="p" href="sec-custom-css-names.html"><img src="icons/prev.png" alt="Prev"></a> </td>
<th width="60%" align="center"> </th>
<td width="20%" align="right"> <a accesskey="n" href="sec-using-glib-dispatcher.html"><img src="icons/next.png" alt="Next"></a>
</td>
</tr>
</table>
<hr>
</div>
<div class="chapter">
<div class="titlepage"><div><div><h1 class="title">
<a name="chapter-multi-threaded-programs"></a>Chapter 29. Multi-threaded programs</h1></div></div></div>
<div class="toc">
<p><b>Table of Contents</b></p>
<ul class="toc">
<li><span class="section"><a href="chapter-multi-threaded-programs.html#sec-the-constraints">The constraints</a></span></li>
<li><span class="section"><a href="sec-using-glib-dispatcher.html">Using Glib::Dispatcher</a></span></li>
<li><span class="section"><a href="sec-multithread-example.html">Example</a></span></li>
</ul>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="sec-the-constraints"></a>The constraints</h2></div></div></div>
<p>
Care is required when writing programs based on <span class="application">gtkmm</span> using
multiple threads of execution, arising from the fact that
<span class="application">libsigc++</span>, and in particular
<code class="classname">sigc::trackable</code>, are not thread-safe. That's
because none of the complex interactions that occur behind the scenes
when using <span class="application">libsigc++</span> are protected by a
mutex or other means of synchronization.
<a href="#ftn.id7073" class="footnote" name="id7073"><sup class="footnote">[1]</sup></a>
</p>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="the-rules"></a>The rules</h3></div></div></div>
<p>
This requires a number of rules to be observed when writing
multi-threaded programs using <span class="application">gtkmm</span>. These are set out below, but
one point to note is that extra care is required when deriving classes
from <code class="classname">sigc::trackable</code>, because the effects are
unintuitive (see particularly points 4 and 5 below).
</p>
<div class="orderedlist"><ol class="orderedlist" type="1">
<li class="listitem">
<p>
Use <code class="classname">Glib::Dispatcher</code> to invoke <span class="application">gtkmm</span> functions
from worker threads (this is dealt with in more detail in the next
section).
</p>
</li>
<li class="listitem">
<p>
A <code class="classname">sigc::signal</code> object should be regarded as
owned by the thread which created it. Only that thread should connect
a <code class="classname">sigc::slot</code> object to the signal object, and
only that thread should <code class="methodname">emit()</code> or call
<code class="methodname">operator()()</code> on the signal, or null any
connected <code class="classname">sigc::slot</code> object. It follows
(amongst other things) that any signal object provided by a <span class="application">gtkmm</span>
widget should only be operated on in the main GUI thread and any
object deriving from <code class="classname">sigc::trackable</code> having its
non-static methods referenced by slots connected to the signal object
should only be destroyed in that thread.
</p>
</li>
<li class="listitem">
<p>
Any <code class="classname">sigc::connection</code> object should be regarded
as owned by the thread in which the method returning the
<code class="classname">sigc::connection</code> object was called. Only that
thread should call <code class="classname">sigc::connection</code> methods on
the object.
</p>
</li>
<li class="listitem">
<p>
A <code class="classname">sigc::slot</code> object created by a call to
<code class="function">sigc::mem_fun()</code> which references a method of a
class deriving from <code class="classname">sigc::trackable</code> should
never be copied to another thread, nor destroyed by a different thread
than the one which created it.
</p>
</li>
<li class="listitem">
<p>
If a particular class object derives from
<code class="classname">sigc::trackable</code>, only one thread should create
<code class="classname">sigc::slot</code> objects representing any of the
class's non-static methods by calling
<code class="function">sigc::mem_fun()</code>. The first thread to create such
a slot should be regarded as owning the relevant object for the
purpose of creating further slots referencing <span class="emphasis"><em>any</em></span>
of its non-static methods using that function, or nulling those slots
by disconnecting them or destroying the trackable object.
</p>
</li>
<li class="listitem">
<p>
Although <span class="application">glib</span> is itself thread-safe, any
<span class="application">glibmm</span> wrappers which use
<span class="application">libsigc++</span> will not be. So for example, only
the thread in which a main loop runs should call
<code class="methodname">Glib::SignalIdle::connect()</code>,
<code class="methodname">Glib::SignalIO::connect()</code>,
<code class="methodname">Glib::SignalTimeout::connect()</code>,
<code class="methodname">Glib::SignalTimeout::connect_seconds</code>
for that main loop, or manipulate any
<code class="classname">sigc::connection</code> object returned by them.
</p>
<p>
The connect*_once() variants,
<code class="methodname">Glib::SignalIdle::connect_once()</code>,
<code class="methodname">Glib::SignalTimeout::connect_once()</code>,
<code class="methodname">Glib::SignalTimeout::connect_seconds_once()</code>,
are thread-safe for any case where the slot is not created by a call to
<code class="function">sigc::mem_fun()</code> which represents a method of a class
deriving from <code class="classname">sigc::trackable</code>.
</p>
</li>
</ol></div>
</div>
</div>
<div class="footnotes">
<br><hr style="width:100; text-align:left;margin-left: 0">
<div id="ftn.id7073" class="footnote">
<p><a href="#id7073" class="para"><sup class="para">[1] </sup></a>
These interactions arise from the fact that, amongst other things, a
class inheriting from <code class="classname">sigc::trackable</code> will, via
that inheritance, have a <code class="classname">std::list</code> object
keeping track of slots created by calls to
<code class="function">sigc::mem_fun()</code> representing any of its
non-static methods (more particularly it keeps a list of callbacks
which will null the connected slots on its destruction). Each
<code class="classname">sigc::slot</code> object also keeps, via
<code class="classname">sigc::slot_rep</code>, its own
<code class="classname">sigc::trackable</code> object to track any
<code class="classname">sigc::connection</code> objects which it needs to
inform about its demise, and also has a function to deregister itself
from any <code class="classname">sigc::trackable</code> on disconnection or
destruction. <code class="classname">sigc::signal</code> objects also keep
lists of slots, which will be updated by a call to their
<code class="methodname">connect()</code> method or calls to any
<code class="classname">sigc::connection</code> object relating to such a
connection.
</p>
</div>
</div>
</div>
<div class="navfooter">
<hr>
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left">
<a accesskey="p" href="sec-custom-css-names.html"><img src="icons/prev.png" alt="Prev"></a> </td>
<td width="20%" align="center"> </td>
<td width="40%" align="right"> <a accesskey="n" href="sec-using-glib-dispatcher.html"><img src="icons/next.png" alt="Next"></a>
</td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Custom CSS Names </td>
<td width="20%" align="center"><a accesskey="h" href="index.html"><img src="icons/home.png" alt="Home"></a></td>
<td width="40%" align="right" valign="top"> Using Glib::Dispatcher</td>
</tr>
</table>
</div>
</body>
</html>
|