logo top
Main Page   Widgets   Namespaces   Book  

thread/dispatcher.cc

A Glib::Dispatcher example.
/* * Glib::Dispatcher example -- cross thread signalling * by Daniel Elstner <daniel.elstner@gmx.net> * * modified to only use glibmm * by J. Abelardo Gutierrez <jabelardo@cantv.net> * * Copyright (c) 2002-2003 Free Software Foundation */ #include <glibmm.h> #include <algorithm> #include <functional> #include <iostream> #include <list> #include <memory> namespace { class ThreadProgress { public: explicit ThreadProgress(int id); ~ThreadProgress(); void launch(); void join(); sigc::signal<void>& signal_finished(); int id() const; private: Glib::Thread* thread_; int id_; unsigned int progress_; Glib::Dispatcher signal_increment_; sigc::signal<void> signal_finished_; void progress_increment(); void thread_function(); }; class Application : public sigc::trackable { public: Application(); virtual ~Application(); void launch_threads(); void run(); private: Glib::RefPtr<Glib::MainLoop> main_loop_; std::list<ThreadProgress*> progress_list_; void on_progress_finished(ThreadProgress* thread_progress); }; ThreadProgress::ThreadProgress(int id) : thread_ (0), id_ (id), progress_ (0) { // Connect to the cross-thread signal. signal_increment_.connect(sigc::mem_fun(*this, &ThreadProgress::progress_increment)); } ThreadProgress::~ThreadProgress() {} void ThreadProgress::launch() { // Create a joinable thread. thread_ = Glib::Thread::create(sigc::mem_fun(*this, &ThreadProgress::thread_function), true); } void ThreadProgress::join() { thread_->join(); } sigc::signal<void>& ThreadProgress::signal_finished() { return signal_finished_; } int ThreadProgress::id() const { return id_; } void ThreadProgress::progress_increment() { // Use an integer because floating point arithmetic is inaccurate -- // we want to finish *exactly* after the 100th increment. ++progress_; std::cout << "Thread " << id_ << ": " << progress_ << '%' << std::endl; if(progress_ >= 100) signal_finished_(); } void ThreadProgress::thread_function() { Glib::Rand rand; int usecs = 5000; for(int i = 0; i < 100; ++i) { usecs = rand.get_int_range(std::max(0, usecs - 1000 - i), std::min(20000, usecs + 1000 + i)); Glib::usleep(usecs); // Tell the main thread to increment the progress value. signal_increment_(); } } Application::Application() : main_loop_ (Glib::MainLoop::create()) { std::cout << "Thread Dispatcher Example." << std::endl; for(int i = 1; i <= 5; ++i) { std::auto_ptr<ThreadProgress> progress (new ThreadProgress(i)); progress_list_.push_back(progress.get()); progress->signal_finished().connect( sigc::bind(sigc::mem_fun(*this, &Application::on_progress_finished), progress.release())); } } Application::~Application() {} void Application::launch_threads() { std::for_each(progress_list_.begin(), progress_list_.end(), std::mem_fun(&ThreadProgress::launch)); } void Application::run() { main_loop_->run(); } void Application::on_progress_finished(ThreadProgress* thread_progress) { { const std::auto_ptr<ThreadProgress> progress (thread_progress); progress_list_.remove(progress.get()); progress->join(); std::cout << "Thread " << progress->id() << ": finished." << std::endl; } if(progress_list_.empty()) main_loop_->quit(); } } // anonymous namespace int main(int, char**) { Glib::thread_init(); Application application; // Install a one-shot idle handler to launch the threads Glib::signal_idle().connect( sigc::bind_return(sigc::mem_fun(application, &Application::launch_threads), false)); application.run(); return 0; }
00001 /* 00002 * Glib::Dispatcher example -- cross thread signalling 00003 * by Daniel Elstner <daniel.elstner@gmx.net> 00004 * 00005 * modified to only use glibmm 00006 * by J. Abelardo Gutierrez <jabelardo@cantv.net> 00007 * 00008 * Copyright (c) 2002-2003 Free Software Foundation 00009 */ 00010 00011 #include <glibmm.h> 00012 00013 #include <algorithm> 00014 #include <functional> 00015 #include <iostream> 00016 #include <list> 00017 #include <memory> 00018 00019 00020 namespace 00021 { 00022 00023 class ThreadProgress 00024 { 00025 public: 00026 explicit ThreadProgress(int id); 00027 ~ThreadProgress(); 00028 00029 void launch(); 00030 void join(); 00031 00032 sigc::signal<void>& signal_finished(); 00033 int id() const; 00034 00035 private: 00036 Glib::Thread* thread_; 00037 int id_; 00038 unsigned int progress_; 00039 Glib::Dispatcher signal_increment_; 00040 sigc::signal<void> signal_finished_; 00041 00042 void progress_increment(); 00043 void thread_function(); 00044 }; 00045 00046 class Application : public sigc::trackable 00047 { 00048 public: 00049 Application(); 00050 virtual ~Application(); 00051 00052 void launch_threads(); 00053 void run(); 00054 00055 private: 00056 Glib::RefPtr<Glib::MainLoop> main_loop_; 00057 std::list<ThreadProgress*> progress_list_; 00058 00059 void on_progress_finished(ThreadProgress* thread_progress); 00060 }; 00061 00062 00063 ThreadProgress::ThreadProgress(int id) 00064 : 00065 thread_ (0), 00066 id_ (id), 00067 progress_ (0) 00068 { 00069 // Connect to the cross-thread signal. 00070 signal_increment_.connect(sigc::mem_fun(*this, &ThreadProgress::progress_increment)); 00071 } 00072 00073 ThreadProgress::~ThreadProgress() 00074 {} 00075 00076 void ThreadProgress::launch() 00077 { 00078 // Create a joinable thread. 00079 thread_ = Glib::Thread::create(sigc::mem_fun(*this, &ThreadProgress::thread_function), true); 00080 } 00081 00082 void ThreadProgress::join() 00083 { 00084 thread_->join(); 00085 } 00086 00087 sigc::signal<void>& ThreadProgress::signal_finished() 00088 { 00089 return signal_finished_; 00090 } 00091 00092 int ThreadProgress::id() const 00093 { 00094 return id_; 00095 } 00096 00097 void ThreadProgress::progress_increment() 00098 { 00099 // Use an integer because floating point arithmetic is inaccurate -- 00100 // we want to finish *exactly* after the 100th increment. 00101 ++progress_; 00102 00103 std::cout << "Thread " << id_ << ": " << progress_ << '%' << std::endl; 00104 00105 if(progress_ >= 100) 00106 signal_finished_(); 00107 } 00108 00109 void ThreadProgress::thread_function() 00110 { 00111 Glib::Rand rand; 00112 int usecs = 5000; 00113 00114 for(int i = 0; i < 100; ++i) 00115 { 00116 usecs = rand.get_int_range(std::max(0, usecs - 1000 - i), std::min(20000, usecs + 1000 + i)); 00117 Glib::usleep(usecs); 00118 00119 // Tell the main thread to increment the progress value. 00120 signal_increment_(); 00121 } 00122 } 00123 00124 Application::Application() 00125 : 00126 main_loop_ (Glib::MainLoop::create()) 00127 { 00128 std::cout << "Thread Dispatcher Example." << std::endl; 00129 00130 for(int i = 1; i <= 5; ++i) 00131 { 00132 std::auto_ptr<ThreadProgress> progress (new ThreadProgress(i)); 00133 progress_list_.push_back(progress.get()); 00134 00135 progress->signal_finished().connect( 00136 sigc::bind(sigc::mem_fun(*this, &Application::on_progress_finished), progress.release())); 00137 } 00138 } 00139 00140 Application::~Application() 00141 {} 00142 00143 void Application::launch_threads() 00144 { 00145 std::for_each(progress_list_.begin(), progress_list_.end(), 00146 std::mem_fun(&ThreadProgress::launch)); 00147 } 00148 00149 void Application::run() 00150 { 00151 main_loop_->run(); 00152 } 00153 00154 void Application::on_progress_finished(ThreadProgress* thread_progress) 00155 { 00156 { 00157 const std::auto_ptr<ThreadProgress> progress (thread_progress); 00158 00159 progress_list_.remove(progress.get()); 00160 progress->join(); 00161 00162 std::cout << "Thread " << progress->id() << ": finished." << std::endl; 00163 } 00164 00165 if(progress_list_.empty()) 00166 main_loop_->quit(); 00167 } 00168 00169 } // anonymous namespace 00170 00171 00172 int main(int, char**) 00173 { 00174 Glib::thread_init(); 00175 00176 Application application; 00177 00178 // Install a one-shot idle handler to launch the threads 00179 Glib::signal_idle().connect( 00180 sigc::bind_return(sigc::mem_fun(application, &Application::launch_threads), false)); 00181 00182 application.run(); 00183 00184 return 0; 00185 } 00186

Generated for glibmm 2.4 by Doxygen 1.3.7 © 1997-2001