<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://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.11"/> <title>glibmm: thread/dispatcher.cc</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="doxygen.css" rel="stylesheet" type="text/css" /> <link href="doxygen-extra.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">glibmm  <span id="projectnumber">2.60.0</span> </div> </td> </tr> </tbody> </table> </div> <!-- end header part --> <!-- Generated by Doxygen 1.8.11 --> <div id="navrow1" class="tabs"> <ul class="tablist"> <li><a href="index.html"><span>Main Page</span></a></li> <li><a href="pages.html"><span>Related Pages</span></a></li> <li><a href="modules.html"><span>Modules</span></a></li> <li><a href="namespaces.html"><span>Namespaces</span></a></li> <li><a href="annotated.html"><span>Classes</span></a></li> <li><a href="examples.html"><span>Examples</span></a></li> </ul> </div> </div><!-- top --> <div class="header"> <div class="headertitle"> <div class="title">thread/dispatcher.cc</div> </div> </div><!--header--> <div class="contents"> <p>A <a class="el" href="classGlib_1_1Dispatcher.html" title="Signal class for inter-thread communication. ">Glib::Dispatcher</a> example.</p> <div class="fragment"><div class="line"><span class="comment">/*</span></div><div class="line"><span class="comment"> * Glib::Dispatcher example -- cross thread signalling</span></div><div class="line"><span class="comment"> * by Daniel Elstner <daniel.kitta@gmail.com></span></div><div class="line"><span class="comment"> *</span></div><div class="line"><span class="comment"> * modified to only use glibmm</span></div><div class="line"><span class="comment"> * by J. Abelardo Gutierrez <jabelardo@cantv.net></span></div><div class="line"><span class="comment"> *</span></div><div class="line"><span class="comment"> * Copyright (c) 2002-2003 Free Software Foundation</span></div><div class="line"><span class="comment"> */</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include <glibmm.h></span></div><div class="line"></div><div class="line"><span class="preprocessor">#include <<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00038.html">algorithm</a>></span></div><div class="line"><span class="preprocessor">#include <<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00071.html">functional</a>></span></div><div class="line"><span class="preprocessor">#include <<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00086.html">iostream</a>></span></div><div class="line"><span class="preprocessor">#include <<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00158.html">thread</a>></span></div><div class="line"><span class="preprocessor">#include <<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00182.html">vector</a>></span></div><div class="line"></div><div class="line"><span class="keyword">namespace</span></div><div class="line">{</div><div class="line"></div><div class="line"><span class="comment">/*</span></div><div class="line"><span class="comment"> * Note that it does not make sense for this class to inherit from</span></div><div class="line"><span class="comment"> * sigc::trackable, as doing so would only give a false sense of security.</span></div><div class="line"><span class="comment"> * Once the thread launch has been triggered, the object has to stay alive</span></div><div class="line"><span class="comment"> * until the thread has been joined again. The code running in the thread</span></div><div class="line"><span class="comment"> * assumes the existence of the object. If it is destroyed earlier, the</span></div><div class="line"><span class="comment"> * program will crash, with sigc::trackable or without it.</span></div><div class="line"><span class="comment"> */</span></div><div class="line"><span class="keyword">class </span>ThreadProgress</div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line"> <span class="keyword">explicit</span> ThreadProgress(<span class="keywordtype">int</span> the_id);</div><div class="line"> ~ThreadProgress();</div><div class="line"></div><div class="line"> <span class="keywordtype">int</span> id() <span class="keyword">const</span>;</div><div class="line"> <span class="keywordtype">void</span> <a name="a0"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01475.html#ga6f4ad125d364f01560e2ed20a3c8bb5b">launch</a>();</div><div class="line"> <span class="keywordtype">void</span> join();</div><div class="line"> <span class="keywordtype">bool</span> unfinished() <span class="keyword">const</span>;</div><div class="line"></div><div class="line"> <a name="_a1"></a><a class="codeRef" href="../../../libsigc++-2.0/reference/html/classsigc_1_1signal.html">sigc::signal<void()></a>& signal_finished();</div><div class="line"></div><div class="line"><span class="keyword">private</span>:</div><div class="line"> <span class="keyword">enum</span></div><div class="line"> {</div><div class="line"> ITERATIONS = 100</div><div class="line"> };</div><div class="line"></div><div class="line"> <span class="comment">// Note that the thread does not write to the member data at all. It only</span></div><div class="line"> <span class="comment">// reads signal_increment_, which is only written to before the thread is</span></div><div class="line"> <span class="comment">// launched. Therefore, no locking is required.</span></div><div class="line"> <a name="_a2"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a02972.html">std::thread</a>* thread_;</div><div class="line"> <span class="keywordtype">int</span> id_;</div><div class="line"> <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> progress_;</div><div class="line"> <a name="_a3"></a><a class="code" href="classGlib_1_1Dispatcher.html">Glib::Dispatcher</a> signal_increment_;</div><div class="line"> <a class="codeRef" href="../../../libsigc++-2.0/reference/html/classsigc_1_1signal.html">sigc::signal<void()></a> signal_finished_;</div><div class="line"></div><div class="line"> <span class="keywordtype">void</span> progress_increment();</div><div class="line"> <span class="keywordtype">void</span> thread_function();</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">class </span>Application : <span class="keyword">public</span> <a name="_a4"></a><a class="codeRef" href="../../../libsigc++-2.0/reference/html/structsigc_1_1trackable.html">sigc::trackable</a></div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line"> Application();</div><div class="line"> ~Application();</div><div class="line"></div><div class="line"> <span class="keywordtype">void</span> run();</div><div class="line"></div><div class="line"><span class="keyword">private</span>:</div><div class="line"> <a name="_a5"></a><a class="code" href="classGlib_1_1RefPtr.html">Glib::RefPtr<Glib::MainLoop></a> main_loop_;</div><div class="line"> <a name="_a6"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a06912.html">std::vector<ThreadProgress*></a> progress_threads_;</div><div class="line"></div><div class="line"> <span class="keywordtype">void</span> launch_threads();</div><div class="line"> <span class="keywordtype">void</span> on_progress_finished(ThreadProgress* thread_progress);</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">template</span> <<span class="keyword">class</span> T></div><div class="line"><span class="keyword">class </span>DeletePtr : <span class="keyword">public</span> <a name="_a7"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a06392.html">std::unary_function</a><void, T></div><div class="line">{</div><div class="line"><span class="keyword">public</span>:</div><div class="line"> <span class="keywordtype">void</span> operator()(T ptr)<span class="keyword"> const </span>{ <span class="keyword">delete</span> ptr; }</div><div class="line">};</div><div class="line"></div><div class="line">ThreadProgress::ThreadProgress(<span class="keywordtype">int</span> the_id) : thread_(<span class="keyword">nullptr</span>), id_(the_id), progress_(0)</div><div class="line">{</div><div class="line"> <span class="comment">// Connect to the cross-thread signal.</span></div><div class="line"> signal_increment_.connect(<a name="a8"></a><a class="codeRef" href="../../../libsigc++-2.0/reference/html/group__mem__fun.html#gadf6b6d22c503b439019f0a2e77352419">sigc::mem_fun</a>(*<span class="keyword">this</span>, &ThreadProgress::progress_increment));</div><div class="line">}</div><div class="line"></div><div class="line">ThreadProgress::~ThreadProgress()</div><div class="line">{</div><div class="line"> <span class="comment">// It is an error if the thread is still running at this point.</span></div><div class="line"> g_return_if_fail(thread_ == <span class="keyword">nullptr</span>);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">int</span></div><div class="line">ThreadProgress::id()<span class="keyword"> const</span></div><div class="line"><span class="keyword"></span>{</div><div class="line"> <span class="keywordflow">return</span> id_;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span></div><div class="line"><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01475.html#ga6f4ad125d364f01560e2ed20a3c8bb5b">ThreadProgress::launch</a>()</div><div class="line">{</div><div class="line"> <span class="comment">// Create a joinable thread.</span></div><div class="line"> thread_ = <span class="keyword">new</span> <a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a02972.html">std::thread</a>([<span class="keyword">this</span>]() { thread_function(); });</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span></div><div class="line">ThreadProgress::join()</div><div class="line">{</div><div class="line"> thread_->join();</div><div class="line"> <span class="keyword">delete</span> thread_;</div><div class="line"> thread_ = <span class="keyword">nullptr</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">bool</span></div><div class="line">ThreadProgress::unfinished()<span class="keyword"> const</span></div><div class="line"><span class="keyword"></span>{</div><div class="line"> <span class="keywordflow">return</span> (progress_ < ITERATIONS);</div><div class="line">}</div><div class="line"></div><div class="line"><a class="codeRef" href="../../../libsigc++-2.0/reference/html/classsigc_1_1signal.html">sigc::signal<void()></a>&</div><div class="line">ThreadProgress::signal_finished()</div><div class="line">{</div><div class="line"> <span class="keywordflow">return</span> signal_finished_;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span></div><div class="line">ThreadProgress::progress_increment()</div><div class="line">{</div><div class="line"> ++progress_;</div><div class="line"> <a name="a9"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01544.html#aaf93fdf0812752e0e02c501dea1b38f0">std::cout</a> << <span class="stringliteral">"Thread "</span> << id_ << <span class="stringliteral">": "</span> << progress_ << <span class="charliteral">'%'</span> << <a name="a10"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01544.html#a8b3758bb8f17c440c7963363f42f69f3">std::endl</a>;</div><div class="line"></div><div class="line"> <span class="keywordflow">if</span> (progress_ >= ITERATIONS)</div><div class="line"> signal_finished_();</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span></div><div class="line">ThreadProgress::thread_function()</div><div class="line">{</div><div class="line"> <a name="_a11"></a><a class="code" href="classGlib_1_1Rand.html">Glib::Rand</a> rand;</div><div class="line"></div><div class="line"> <span class="keywordflow">for</span> (<span class="keyword">auto</span> i = 0; i < ITERATIONS; ++i)</div><div class="line"> {</div><div class="line"> <a name="a12"></a><a class="code" href="namespaceGlib.html#a5d75264c8b47f13fb33f973b0d4fc73e">Glib::usleep</a>(rand.<a name="a13"></a><a class="code" href="classGlib_1_1Rand.html#a182b9a36db153d316baf5efb1ece9fd7">get_int_range</a>(2000, 20000));</div><div class="line"></div><div class="line"> <span class="comment">// Tell the main thread to increment the progress value.</span></div><div class="line"> signal_increment_();</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">Application::Application() : main_loop_(<a name="a14"></a><a class="code" href="classGlib_1_1MainLoop.html#a37a1dcf3cb167cf02260111f533d0b5b">Glib::MainLoop::create</a>()), progress_threads_(5)</div><div class="line">{</div><div class="line"> <span class="keywordflow">try</span></div><div class="line"> {</div><div class="line"> <span class="keywordflow">for</span> (<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a06912.html">std::vector<ThreadProgress*>::size_type</a> i = 0; i < progress_threads_.<a name="a15"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a06912.html#aedc1ee21f6ca2b8304b4f1f430125c8d">size</a>(); ++i)</div><div class="line"> {</div><div class="line"> ThreadProgress* <span class="keyword">const</span> progress = <span class="keyword">new</span> ThreadProgress(i + 1);</div><div class="line"> progress_threads_[i] = progress;</div><div class="line"></div><div class="line"> progress->signal_finished().connect(</div><div class="line"> <a name="a16"></a><a class="codeRef" href="../../../libsigc++-2.0/reference/html/group__bind.html#ga2f099bc6056b32f2a58134ba8537c6f4">sigc::bind</a>(<a class="codeRef" href="../../../libsigc++-2.0/reference/html/group__mem__fun.html#gadf6b6d22c503b439019f0a2e77352419">sigc::mem_fun</a>(*<span class="keyword">this</span>, &Application::on_progress_finished), progress));</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="keywordflow">catch</span> (...)</div><div class="line"> {</div><div class="line"> <span class="comment">// In your own code, you should preferably use a smart pointer</span></div><div class="line"> <span class="comment">// to ensure exception safety.</span></div><div class="line"> <a name="a17"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01487.html#ga36d3b88a382b4ad3bf55aff3f597522d">std::for_each</a>(progress_threads_.begin(), progress_threads_.end(), DeletePtr<ThreadProgress*>());</div><div class="line"> <span class="keywordflow">throw</span>;</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">Application::~Application()</div><div class="line">{</div><div class="line"> <a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01487.html#ga36d3b88a382b4ad3bf55aff3f597522d">std::for_each</a>(progress_threads_.begin(), progress_threads_.end(), DeletePtr<ThreadProgress*>());</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span></div><div class="line">Application::run()</div><div class="line">{</div><div class="line"> <span class="comment">// Install a one-shot idle handler to launch the threads.</span></div><div class="line"> <a name="a18"></a><a class="code" href="group__MainLoop.html#ga76792522d9680a05e232d3519a25f98d">Glib::signal_idle</a>().<a name="a19"></a><a class="code" href="classGlib_1_1SignalIdle.html#a94217dc63e35f96b5cee4c48f2cdd020">connect_once</a>(<a class="codeRef" href="../../../libsigc++-2.0/reference/html/group__mem__fun.html#gadf6b6d22c503b439019f0a2e77352419">sigc::mem_fun</a>(*<span class="keyword">this</span>, &Application::launch_threads));</div><div class="line"></div><div class="line"> main_loop_->run();</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span></div><div class="line">Application::launch_threads()</div><div class="line">{</div><div class="line"> <a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01544.html#aaf93fdf0812752e0e02c501dea1b38f0">std::cout</a> << <span class="stringliteral">"Launching "</span> << progress_threads_.size() << <span class="stringliteral">" threads:"</span> << <a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01544.html#a8b3758bb8f17c440c7963363f42f69f3">std::endl</a>;</div><div class="line"></div><div class="line"> <a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01487.html#ga36d3b88a382b4ad3bf55aff3f597522d">std::for_each</a>(</div><div class="line"> progress_threads_.begin(), progress_threads_.end(), <a name="a20"></a><a class="codeRef" href="../../../libsigc++-2.0/reference/html/group__mem__fun.html#gadf6b6d22c503b439019f0a2e77352419">std::mem_fun</a>(&<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01475.html#ga6f4ad125d364f01560e2ed20a3c8bb5b">ThreadProgress::launch</a>));</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keywordtype">void</span></div><div class="line">Application::on_progress_finished(ThreadProgress* thread_progress)</div><div class="line">{</div><div class="line"> thread_progress->join();</div><div class="line"></div><div class="line"> <a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01544.html#aaf93fdf0812752e0e02c501dea1b38f0">std::cout</a> << <span class="stringliteral">"Thread "</span> << thread_progress->id() << <span class="stringliteral">": finished."</span> << <a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01544.html#a8b3758bb8f17c440c7963363f42f69f3">std::endl</a>;</div><div class="line"></div><div class="line"> <span class="comment">// Quit if it was the last thread to be joined.</span></div><div class="line"> <span class="keywordflow">if</span> (<a name="a21"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01487.html#gaaf6e9995ebbd27994d7c73b375f86088">std::find_if</a>(progress_threads_.begin(), progress_threads_.end(),</div><div class="line"> <a class="codeRef" href="../../../libsigc++-2.0/reference/html/group__mem__fun.html#gadf6b6d22c503b439019f0a2e77352419">std::mem_fun</a>(&ThreadProgress::unfinished)) == progress_threads_.end())</div><div class="line"> {</div><div class="line"> main_loop_->quit();</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">} <span class="comment">// anonymous namespace</span></div><div class="line"></div><div class="line"><span class="keywordtype">int</span></div><div class="line">main(<span class="keywordtype">int</span>, <span class="keywordtype">char</span>**)</div><div class="line">{</div><div class="line"> <a name="a22"></a><a class="code" href="namespaceGlib.html#ac90aee10d0b90e3d8a96a86b5394f87b">Glib::init</a>();</div><div class="line"></div><div class="line"> Application application;</div><div class="line"> application.run();</div><div class="line"></div><div class="line"> <span class="keywordflow">return</span> 0;</div><div class="line">}</div></div><!-- fragment --> </div><!-- contents --> <!-- start footer part --> <hr class="footer"/><address class="footer"><small> Generated on Tue Mar 19 2019 09:56:37 for glibmm by  <a href="http://www.doxygen.org/index.html"> <img class="footer" src="doxygen.png" alt="doxygen"/> </a> 1.8.11 </small></address> </body> </html>