<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"> <title>Example Documentation</title> <link href="doxygen.css" rel="stylesheet" type="text/css"> </head> <body bgcolor="#ffffff"> <table border="0" width="100%"> <tr> <td width="10%" height="40"><img src="../../images/gtkmm_logo.gif" alt="logo" border="0" width="100%" height="100%"/></td> <td width="90%" height="40"><img src="../../images/top.gif" alt="top" width="100%" height="40"/></td> </tr> </table> <center> <a class="qindex" href="../../index.html">Main Page</a> <a href="group__Widgets.html">Widgets</a> <a class="qindex" href="namespaces.html"> Namespaces</a> <a href="../../tutorial/html/index.html"> Book</a> </center> <hr width="100%"/> <!-- Generated by Doxygen 1.3-rc1 --> <h1>thread/dispatcher.cc</h1>A <a class="el" href="classGlib_1_1Dispatcher.html">Glib::Dispatcher</a> example. <p> <div class="fragment"><pre><span class="comment">/*</span> <span class="comment"> * Glib::Dispatcher example -- cross thread signalling</span> <span class="comment"> * by Daniel Elstner <daniel.elstner@gmx.net></span> <span class="comment"> *</span> <span class="comment"> * Copyright (c) 2002 Free Software Foundation</span> <span class="comment"> */</span> <span class="preprocessor">#include <sigc++/class_slot.h></span> <span class="preprocessor">#include <glibmm.h></span> <span class="preprocessor">#include <<a class="code" href="box_8h.html">gtkmm/box.h</a>></span> <span class="preprocessor">#include <<a class="code" href="button_8h.html">gtkmm/button.h</a>></span> <span class="preprocessor">#include <<a class="code" href="buttonbox_8h.html">gtkmm/buttonbox.h</a>></span> <span class="preprocessor">#include <<a class="code" href="gtk_2gtkmm_2main_8h.html">gtkmm/main.h</a>></span> <span class="preprocessor">#include <<a class="code" href="progressbar_8h.html">gtkmm/progressbar.h</a>></span> <span class="preprocessor">#include <<a class="code" href="stock_8h.html">gtkmm/stock.h</a>></span> <span class="preprocessor">#include <<a class="code" href="gtk_2gtkmm_2window_8h.html">gtkmm/window.h</a>></span> <span class="preprocessor">#include <algorithm></span> <span class="preprocessor">#include <functional></span> <span class="preprocessor">#include <list></span> <span class="keyword">namespace</span> <span class="keyword"></span>{ <span class="keyword">class </span>ThreadProgress : <span class="keyword">public</span> Gtk::ProgressBar { <span class="keyword">public</span>: ThreadProgress(); <span class="keyword">virtual</span> ~ThreadProgress(); <span class="keywordtype">void</span> launch(); SigC::Signal0<void>& signal_finished(); <span class="keyword">private</span>: <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> progress_; <a name="_a1"></a><a class="code" href="classGlib_1_1Dispatcher.html">Glib::Dispatcher</a> signal_increment_; SigC::Signal0<void> signal_finished_; <span class="keywordtype">void</span> progress_increment(); <span class="keywordtype">void</span> thread_function(); }; <span class="keyword">class </span>MainWindow : <span class="keyword">public</span> Gtk::Window { <span class="keyword">public</span>: MainWindow(); <span class="keyword">virtual</span> ~MainWindow(); <span class="keywordtype">void</span> launch_threads(); <span class="keyword">protected</span>: <span class="keyword">virtual</span> <span class="keywordtype">bool</span> on_delete_event(GdkEventAny* event); <span class="keyword">private</span>: std::list<ThreadProgress*> progress_bars_; <a name="_a2"></a><a class="code" href="classGtk_1_1Button.html">Gtk::Button</a>* close_button_; <span class="keywordtype">void</span> on_progress_finished(ThreadProgress* progress); }; ThreadProgress::ThreadProgress() : progress_ (0) { <span class="comment">// Connect to the cross-thread signal.</span> signal_increment_.connect(SigC::slot(*<span class="keyword">this</span>, &ThreadProgress::progress_increment)); } ThreadProgress::~ThreadProgress() {} <span class="keywordtype">void</span> ThreadProgress::launch() { <span class="comment">// Create a non-joinable thread -- it's deleted automatically on thread exit.</span> <a name="a3"></a><a class="code" href="classGlib_1_1Thread.html#d0">Glib::Thread::create</a>(SigC::slot_class(*<span class="keyword">this</span>, &ThreadProgress::thread_function), <span class="keyword">false</span>); } SigC::Signal0<void>& ThreadProgress::signal_finished() { <span class="keywordflow">return</span> signal_finished_; } <span class="keywordtype">void</span> ThreadProgress::progress_increment() { <span class="comment">// Use an integer because floating point arithmetic is inaccurate --</span> <span class="comment">// we want to finish *exactly* after the 1000th increment.</span> ++progress_; <span class="keyword">const</span> <span class="keywordtype">double</span> fraction = double(progress_) / 1000.0; set_fraction(std::min(fraction, 1.0)); <span class="keywordflow">if</span>(progress_ >= 1000) signal_finished_(); } <span class="keywordtype">void</span> ThreadProgress::thread_function() { <a name="_a4"></a><a class="code" href="classGlib_1_1Rand.html">Glib::Rand</a> rand; <span class="keywordtype">int</span> usecs = 5000; <span class="keywordflow">for</span>(<span class="keywordtype">int</span> i = 0; i < 1000; ++i) { usecs = rand.<a name="a5"></a><a class="code" href="classGlib_1_1Rand.html#a6">get_int_range</a>(std::max(0, usecs - 1000 - i), std::min(20000, usecs + 1000 + i)); <a name="a6"></a><a class="code" href="namespaceGlib.html#a230">Glib::usleep</a>(usecs); <span class="comment">// Tell the GUI thread to increment the progress bar value.</span> signal_increment_(); } } MainWindow::MainWindow() : close_button_ (0) { set_title(<span class="stringliteral">"Thread Dispatcher Example"</span>); <a name="_a7"></a><a class="code" href="classGtk_1_1VBox.html">Gtk::VBox</a> *<span class="keyword">const</span> vbox = <span class="keyword">new</span> <a class="code" href="classGtk_1_1VBox.html">Gtk::VBox</a>(<span class="keyword">false</span>, 10); <a class="code" href="namespaceGtk_1_1Stock.html#a70">add</a>(*Gtk::manage(vbox)); vbox-><a name="a8"></a><a class="code" href="classGtk_1_1Container.html#a3">set_border_width</a>(10); <span class="keywordflow">for</span>(<span class="keywordtype">int</span> i = 0; i < 5; ++i) { ThreadProgress *<span class="keyword">const</span> progress = <span class="keyword">new</span> ThreadProgress(); vbox-><a name="a9"></a><a class="code" href="classGtk_1_1Box.html#a3">pack_start</a>(*Gtk::manage(progress), Gtk::PACK_SHRINK); progress_bars_.push_back(progress); progress->signal_finished().connect( SigC::bind(SigC::slot(*<span class="keyword">this</span>, &MainWindow::on_progress_finished), progress)); } <a name="_a10"></a><a class="code" href="classGtk_1_1ButtonBox.html">Gtk::ButtonBox</a> *<span class="keyword">const</span> button_box = <span class="keyword">new</span> <a name="_a11"></a><a class="code" href="classGtk_1_1HButtonBox.html">Gtk::HButtonBox</a>(); vbox-><a name="a12"></a><a class="code" href="classGtk_1_1Box.html#a5">pack_end</a>(*Gtk::manage(button_box), Gtk::PACK_SHRINK); close_button_ = <span class="keyword">new</span> <a class="code" href="classGtk_1_1Button.html">Gtk::Button</a>(Gtk::Stock::CLOSE); button_box-><a class="code" href="classGtk_1_1Box.html#a3">pack_start</a>(*Gtk::manage(close_button_), Gtk::PACK_SHRINK); close_button_->set_flags(Gtk::CAN_DEFAULT); close_button_->grab_default(); close_button_->set_sensitive(<span class="keyword">false</span>); close_button_->signal_clicked().connect(SigC::slot(*<span class="keyword">this</span>, &<a class="code" href="classGtk_1_1Widget.html#a6">Gtk::Widget::hide</a>)); show_all_children(); set_default_size(300, -1); } MainWindow::~MainWindow() {} <span class="keywordtype">void</span> MainWindow::launch_threads() { std::for_each( progress_bars_.begin(), progress_bars_.end(), std::mem_fun(&ThreadProgress::launch)); } <span class="keywordtype">bool</span> MainWindow::on_delete_event(GdkEventAny*) { <span class="comment">// Don't allow closing the window before all threads finished.</span> <span class="keywordflow">return</span> !progress_bars_.empty(); } <span class="keywordtype">void</span> MainWindow::on_progress_finished(ThreadProgress* progress) { progress_bars_.remove(progress); <span class="comment">// Enable the close button when all threads finished.</span> <span class="keywordflow">if</span>(progress_bars_.empty()) close_button_->set_sensitive(<span class="keyword">true</span>); } } <span class="comment">// anonymous namespace</span> <span class="keywordtype">int</span> main(<span class="keywordtype">int</span> argc, <span class="keywordtype">char</span>** argv) { <a name="a13"></a><a class="code" href="group__Threads.html#a0">Glib::thread_init</a>(); <a name="_a14"></a><a class="code" href="classGtk_1_1Main.html">Gtk::Main</a> main_instance (&argc, &argv); MainWindow window; <span class="comment">// Install a one-shot idle handler to launch the threads</span> <span class="comment">// right after the main window has been displayed.</span> <a name="a15"></a><a class="code" href="group__MainLoop.html#a8">Glib::signal_idle</a>().connect( SigC::bind_return(SigC::slot(window, &MainWindow::launch_threads), <span class="keyword">false</span>)); <a name="a16"></a><a class="code" href="classGtk_1_1Main.html#d1">Gtk::Main::run</a>(window); <span class="keywordflow">return</span> 0; } </pre></div><hr><address><small> Generated for gtkmm by <a href="http://www.doxygen.org/index.html"> Doxygen</a> 1.3-rc1 © 1997-2001</small></address> </body> </html>