Sophie

Sophie

distrib > Mandriva > 2010.0 > x86_64 > by-pkgid > 7f3e5f74d754b480ec33648905c4afae > files > 685

glibmm2.4-doc-2.22.1-1mdv2010.0.x86_64.rpm

<!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&#160;Page</span></a></li>
      <li><a href="pages.html"><span>Related&#160;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 &lt;daniel.kitta@gmail.com&gt;</span>
<span class="comment"> *</span>
<span class="comment"> * modified to only use glibmm</span>
<span class="comment"> * by J. Abelardo Gutierrez &lt;jabelardo@cantv.net&gt;</span>
<span class="comment"> *</span>
<span class="comment"> * Copyright (c) 2002-2003 Free Software Foundation</span>
<span class="comment"> */</span>

<span class="preprocessor">#include &lt;glibmm.h&gt;</span>

<span class="preprocessor">#include &lt;<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00607.html">algorithm</a>&gt;</span>
<span class="preprocessor">#include &lt;<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00750.html">functional</a>&gt;</span>
<span class="preprocessor">#include &lt;<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00779.html">iostream</a>&gt;</span>
<span class="preprocessor">#include &lt;<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00947.html">vector</a>&gt;</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&lt;void&gt;</a>&amp; 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&lt;void&gt;</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&amp;lt;&amp;gt; is a reference-counting shared smartpointer.">Glib::RefPtr&lt;Glib::MainLoop&gt;</a> main_loop_;
  <a name="_a5"></a><a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00601.html">std::vector&lt;ThreadProgress*&gt;</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> &lt;<span class="keyword">class</span> T&gt;
<span class="keyword">class </span>DeletePtr : <span class="keyword">public</span> std::unary_function&lt;void, T&gt;
{
<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>, &amp;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>, &amp;ThreadProgress::thread_function), <span class="keyword">true</span>);
}

<span class="keywordtype">void</span> ThreadProgress::join()
{
  thread_-&gt;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_ &lt; ITERATIONS);
}

<a class="codeRef" href="../../../libsigc++-2.0/reference/html/classsigc_1_1signal.html">sigc::signal&lt;void&gt;</a>&amp; 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> &lt;&lt; <span class="stringliteral">&quot;Thread &quot;</span> &lt;&lt; id_ &lt;&lt; <span class="stringliteral">&quot;: &quot;</span> &lt;&lt; progress_ &lt;&lt; <span class="charliteral">&apos;%&apos;</span> &lt;&lt; <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_ &gt;= 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 &lt; 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&apos;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&lt;ThreadProgress*&gt;::size_type</a> i = 0; i &lt; progress_threads_.size(); ++i)
    {
      ThreadProgress *<span class="keyword">const</span> progress = <span class="keyword">new</span> ThreadProgress(i + 1);
      progress_threads_[i] = progress;

      progress-&gt;signal_finished().connect(
          sigc::bind&lt;1&gt;(<a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01026.html#ga46b3aee55bddccc454ea4f8edc26ffa7">sigc::mem_fun</a>(*<span class="keyword">this</span>, &amp;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&lt;ThreadProgress*&gt;());
    <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&lt;ThreadProgress*&gt;());
}

<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>, &amp;Application::launch_threads), <span class="keyword">false</span>));

  main_loop_-&gt;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> &lt;&lt; <span class="stringliteral">&quot;Launching &quot;</span> &lt;&lt; progress_threads_.size() &lt;&lt; <span class="stringliteral">&quot; threads:&quot;</span> &lt;&lt; <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>(&amp;ThreadProgress::launch));
}

<span class="keywordtype">void</span> Application::on_progress_finished(ThreadProgress* thread_progress)
{
  thread_progress-&gt;join();

  <a class="codeRef" href="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a00971.html#aaf93fdf0812752e0e02c501dea1b38f0">std::cout</a> &lt;&lt; <span class="stringliteral">&quot;Thread &quot;</span> &lt;&lt; thread_progress-&gt;id() &lt;&lt; <span class="stringliteral">&quot;: finished.&quot;</span> &lt;&lt; <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>(&amp;ThreadProgress::unfinished)) == progress_threads_.end())
  {
    main_loop_-&gt;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&#160;
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.6.1 </small></address>
</body>
</html>