<!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"/> <title>glibmm: thread/dispatcher.cc</title> <link href="tabs.css" rel="stylesheet" type="text/css"/> <link href="doxygen.css" rel="stylesheet" type="text/css"/> </head> <body> <!-- Generated by Doxygen 1.6.1 --> <div class="navigation" id="top"> <div class="tabs"> <ul> <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> <div class="contents"> <h1>thread/dispatcher.cc</h1><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"><pre class="fragment"><span class="comment">/*</span> <span class="comment"> * Glib::Dispatcher example -- cross thread signalling</span> <span class="comment"> * by Daniel Elstner <daniel.kitta@gmail.com></span> <span class="comment"> *</span> <span class="comment"> * modified to only use glibmm</span> <span class="comment"> * by J. Abelardo Gutierrez <jabelardo@cantv.net></span> <span class="comment"> *</span> <span class="comment"> * Copyright (c) 2002-2003 Free Software Foundation</span> <span class="comment"> */</span> <span class="preprocessor">#include <glibmm.h></span> <span class="preprocessor">#include <<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00607.html">algorithm</a>></span> <span class="preprocessor">#include <<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00750.html">functional</a>></span> <span class="preprocessor">#include <<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00779.html">iostream</a>></span> <span class="preprocessor">#include <<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00947.html">vector</a>></span> <span class="keyword">namespace</span> { <span class="comment">/*</span> <span class="comment"> * Note that it does not make sense for this class to inherit from</span> <span class="comment"> * sigc::trackable, as doing so would only give a false sense of security.</span> <span class="comment"> * Once the thread launch has been triggered, the object has to stay alive</span> <span class="comment"> * until the thread has been joined again. The code running in the thread</span> <span class="comment"> * assumes the existence of the object. If it is destroyed earlier, the</span> <span class="comment"> * program will crash, with sigc::trackable or without it.</span> <span class="comment"> */</span> <span class="keyword">class </span>ThreadProgress { <span class="keyword">public</span>: <span class="keyword">explicit</span> ThreadProgress(<span class="keywordtype">int</span> <span class="keywordtype">id</span>); <span class="keyword">virtual</span> ~ThreadProgress(); <span class="keywordtype">int</span> id() <span class="keyword">const</span>; <span class="keywordtype">void</span> launch(); <span class="keywordtype">void</span> join(); <span class="keywordtype">bool</span> unfinished() <span class="keyword">const</span>; <a name="_a0"></a><a class="codeRef" href="../../../libsigc++-2.0/reference/html/classsigc_1_1signal.html">sigc::signal<void></a>& signal_finished(); <span class="keyword">private</span>: <span class="keyword">enum</span> { ITERATIONS = 100 }; <span class="comment">// Note that the thread does not write to the member data at all. It only</span> <span class="comment">// reads signal_increment_, which is only written to before the thread is</span> <span class="comment">// lauched. Therefore, no locking is required.</span> <a name="_a1"></a><a class="code" href="classGlib_1_1Thread.html" title="Represents a running thread.">Glib::Thread</a>* thread_; <span class="keywordtype">int</span> id_; <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> progress_; <a name="_a2"></a><a class="code" href="classGlib_1_1Dispatcher.html" title="Signal class for inter-thread communication.">Glib::Dispatcher</a> signal_increment_; <a class="codeRef" href="../../../libsigc++-2.0/reference/html/classsigc_1_1signal.html">sigc::signal<void></a> signal_finished_; <span class="keywordtype">void</span> progress_increment(); <span class="keywordtype">void</span> thread_function(); }; <span class="keyword">class </span>Application : <span class="keyword">public</span> sigc::<a name="_a3"></a><a class="codeRef" href="../../../libsigc++-2.0/reference/html/structsigc_1_1trackable.html">trackable</a> { <span class="keyword">public</span>: Application(); <span class="keyword">virtual</span> ~Application(); <span class="keywordtype">void</span> run(); <span class="keyword">private</span>: <a name="_a4"></a><a class="code" href="classGlib_1_1RefPtr.html" title="RefPtr&lt;&gt; is a reference-counting shared smartpointer.">Glib::RefPtr<Glib::MainLoop></a> main_loop_; <a name="_a5"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00601.html">std::vector<ThreadProgress*></a> progress_threads_; <span class="keywordtype">void</span> launch_threads(); <span class="keywordtype">void</span> on_progress_finished(ThreadProgress* thread_progress); }; <span class="keyword">template</span> <<span class="keyword">class</span> T> <span class="keyword">class </span>DeletePtr : <span class="keyword">public</span> std::unary_function<void, T> { <span class="keyword">public</span>: <span class="keywordtype">void</span> operator()(T ptr)<span class="keyword"> const </span>{ <span class="keyword">delete</span> ptr; } }; ThreadProgress::ThreadProgress(<span class="keywordtype">int</span> <span class="keywordtype">id</span>) : thread_ (0), id_ (<span class="keywordtype">id</span>), progress_ (0) { <span class="comment">// Connect to the cross-thread signal.</span> signal_increment_.connect(<a name="a6"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01026.html#ga46b3aee55bddccc454ea4f8edc26ffa7">sigc::mem_fun</a>(*<span class="keyword">this</span>, &ThreadProgress::progress_increment)); } ThreadProgress::~ThreadProgress() { <span class="comment">// It is an error if the thread is still running at this point.</span> g_return_if_fail(thread_ == 0); } <span class="keywordtype">int</span> ThreadProgress::id()<span class="keyword"> const</span> <span class="keyword"></span>{ <span class="keywordflow">return</span> id_; } <span class="keywordtype">void</span> ThreadProgress::launch() { <span class="comment">// Create a joinable thread.</span> thread_ = <a name="a7"></a><a class="code" href="classGlib_1_1Thread.html#ab165854ff2fc9b454ee4d97050485782" title="Creates a new thread with the priority THREAD_PRIORITY_NORMAL.">Glib::Thread::create</a>(<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01026.html#ga46b3aee55bddccc454ea4f8edc26ffa7">sigc::mem_fun</a>(*<span class="keyword">this</span>, &ThreadProgress::thread_function), <span class="keyword">true</span>); } <span class="keywordtype">void</span> ThreadProgress::join() { thread_->join(); thread_ = 0; } <span class="keywordtype">bool</span> ThreadProgress::unfinished()<span class="keyword"> const</span> <span class="keyword"></span>{ <span class="keywordflow">return</span> (progress_ < ITERATIONS); } <a class="codeRef" href="../../../libsigc++-2.0/reference/html/classsigc_1_1signal.html">sigc::signal<void></a>& ThreadProgress::signal_finished() { <span class="keywordflow">return</span> signal_finished_; } <span class="keywordtype">void</span> ThreadProgress::progress_increment() { ++progress_; <a name="a8"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00971.html#aaf93fdf0812752e0e02c501dea1b38f0">std::cout</a> << <span class="stringliteral">"Thread "</span> << id_ << <span class="stringliteral">": "</span> << progress_ << <span class="charliteral">'%'</span> << <a name="a9"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00971.html#a75c5d34c6c0dcd2c1a01307dbf6ad8c5">std::endl</a>; <span class="keywordflow">if</span> (progress_ >= ITERATIONS) signal_finished_(); } <span class="keywordtype">void</span> ThreadProgress::thread_function() { <a name="_a10"></a><a class="code" href="classGlib_1_1Rand.html">Glib::Rand</a> rand; <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i < ITERATIONS; ++i) { <a name="a11"></a><a class="code" href="namespaceGlib.html#a5d75264c8b47f13fb33f973b0d4fc73e">Glib::usleep</a>(rand.<a name="a12"></a><a class="code" href="classGlib_1_1Rand.html#a182b9a36db153d316baf5efb1ece9fd7">get_int_range</a>(2000, 20000)); <span class="comment">// Tell the main thread to increment the progress value.</span> signal_increment_(); } } Application::Application() : main_loop_ (<a name="a13"></a><a class="code" href="classGlib_1_1MainLoop.html#a37a1dcf3cb167cf02260111f533d0b5b">Glib::MainLoop::create</a>()), progress_threads_ (5) { <span class="comment">// Note that unless you're targetting an embedded platform, you can assume</span> <span class="comment">// exceptions to be enabled. The #ifdef is only here to make the example</span> <span class="comment">// compile in either case; you may ignore it otherwise.</span> <span class="preprocessor">#ifdef GLIBMM_EXCEPTIONS_ENABLED</span> <span class="preprocessor"></span> <span class="keywordflow">try</span> <span class="preprocessor">#endif</span> <span class="preprocessor"></span> { <span class="keywordflow">for</span> (<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00601.html#a0c431c4aa8cb312a241413a5b669c853">std::vector<ThreadProgress*>::size_type</a> i = 0; i < progress_threads_.size(); ++i) { ThreadProgress *<span class="keyword">const</span> progress = <span class="keyword">new</span> ThreadProgress(i + 1); progress_threads_[i] = progress; progress->signal_finished().connect( sigc::bind<1>(<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01026.html#ga46b3aee55bddccc454ea4f8edc26ffa7">sigc::mem_fun</a>(*<span class="keyword">this</span>, &Application::on_progress_finished), progress)); } } <span class="preprocessor">#ifdef GLIBMM_EXCEPTIONS_ENABLED</span> <span class="preprocessor"></span> <span class="keywordflow">catch</span> (...) { <span class="comment">// In your own code, you should preferably use a smart pointer</span> <span class="comment">// to ensure exception safety.</span> <a name="a14"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01015.html#gae7c8a150efe61c9f8a6eacf002a40efb">std::for_each</a>(progress_threads_.begin(), progress_threads_.end(), DeletePtr<ThreadProgress*>()); <span class="keywordflow">throw</span>; } <span class="preprocessor">#endif</span> <span class="preprocessor"></span>} Application::~Application() { <a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01015.html#gae7c8a150efe61c9f8a6eacf002a40efb">std::for_each</a>(progress_threads_.begin(), progress_threads_.end(), DeletePtr<ThreadProgress*>()); } <span class="keywordtype">void</span> Application::run() { <span class="comment">// Install a one-shot idle handler to launch the threads.</span> <a name="a15"></a><a class="code" href="group__MainLoop.html#ga76792522d9680a05e232d3519a25f98d" title="Convenience idle signal.">Glib::signal_idle</a>().connect( <a name="a16"></a><a class="codeRef" href="../../../libsigc++-2.0/reference/html/group__bind.html#g8a001b0bb588d2ac1af712781b89dc8a">sigc::bind_return</a>(<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01026.html#ga46b3aee55bddccc454ea4f8edc26ffa7">sigc::mem_fun</a>(*<span class="keyword">this</span>, &Application::launch_threads), <span class="keyword">false</span>)); main_loop_->run(); } <span class="keywordtype">void</span> Application::launch_threads() { <a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00971.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/a00971.html#a75c5d34c6c0dcd2c1a01307dbf6ad8c5">std::endl</a>; <a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01015.html#gae7c8a150efe61c9f8a6eacf002a40efb">std::for_each</a>(progress_threads_.begin(), progress_threads_.end(), <a name="a17"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01026.html#ga46b3aee55bddccc454ea4f8edc26ffa7">std::mem_fun</a>(&ThreadProgress::launch)); } <span class="keywordtype">void</span> Application::on_progress_finished(ThreadProgress* thread_progress) { thread_progress->join(); <a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00971.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/a00971.html#a75c5d34c6c0dcd2c1a01307dbf6ad8c5">std::endl</a>; <span class="comment">// Quit if it was the last thread to be joined.</span> <span class="keywordflow">if</span> (<a name="a18"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01015.html#ga517b33f33e70a89afc035c904141edd1">std::find_if</a>(progress_threads_.begin(), progress_threads_.end(), <a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01026.html#ga46b3aee55bddccc454ea4f8edc26ffa7">std::mem_fun</a>(&ThreadProgress::unfinished)) == progress_threads_.end()) { main_loop_->quit(); } } } <span class="comment">// anonymous namespace</span> <span class="keywordtype">int</span> main(<span class="keywordtype">int</span>, <span class="keywordtype">char</span>**) { <a name="a19"></a><a class="code" href="group__Threads.html#gab26d01c776801f1fff00753e97af4fc7" title="Initializes the GLib thread system.">Glib::thread_init</a>(); Application application; application.run(); <span class="keywordflow">return</span> 0; } </pre></div> </div> <hr size="1"/><address style="text-align: right;"><small>Generated on Mon Sep 21 11:07:19 2009 for glibmm by  <a href="http://www.doxygen.org/index.html"> <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.6.1 </small></address> </body> </html>