00001
00002
00003
00004
00005
00006
00007
00008
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 : public sigc::trackable
00024 {
00025 public:
00026 explicit ThreadProgress(int id);
00027 virtual ~ThreadProgress();
00028
00029 void launch();
00030 void join();
00031
00032 sigc::signal<void>& signal_finished();
00033 int id() const;
00034
00035 virtual void reference() const { ++ref_count_; }
00036 virtual void unreference() const { if (!(--ref_count_)) delete this; }
00037
00038 private:
00039 Glib::Thread* thread_;
00040 int id_;
00041 unsigned int progress_;
00042 Glib::Dispatcher signal_increment_;
00043 sigc::signal<void> signal_finished_;
00044
00045 void progress_increment();
00046 void thread_function();
00047
00048 mutable int ref_count_;
00049
00050 };
00051
00052 class Application : public sigc::trackable
00053 {
00054 public:
00055 Application();
00056 virtual ~Application();
00057
00058 void launch_threads();
00059 void run();
00060
00061 private:
00062 Glib::RefPtr<Glib::MainLoop> main_loop_;
00063 std::list<ThreadProgress*> progress_list_;
00064 std::list<Glib::RefPtr<ThreadProgress> > progress_ref_list_;
00065
00066 void on_progress_finished(ThreadProgress* thread_progress);
00067 };
00068
00069
00070 ThreadProgress::ThreadProgress(int id)
00071 :
00072 thread_ (0),
00073 id_ (id),
00074 progress_ (0),
00075 ref_count_(0)
00076 {
00077
00078 reference();
00079
00080 signal_increment_.connect(sigc::mem_fun(*this, &ThreadProgress::progress_increment));
00081 }
00082
00083 ThreadProgress::~ThreadProgress()
00084 {}
00085
00086 void ThreadProgress::launch()
00087 {
00088
00089 thread_ = Glib::Thread::create(sigc::mem_fun(*this, &ThreadProgress::thread_function), true);
00090 }
00091
00092 void ThreadProgress::join()
00093 {
00094 thread_->join();
00095 }
00096
00097 sigc::signal<void>& ThreadProgress::signal_finished()
00098 {
00099 return signal_finished_;
00100 }
00101
00102 int ThreadProgress::id() const
00103 {
00104 return id_;
00105 }
00106
00107 void ThreadProgress::progress_increment()
00108 {
00109
00110
00111 ++progress_;
00112
00113 std::cout << "Thread " << id_ << ": " << progress_ << '%' << std::endl;
00114
00115 if(progress_ >= 100)
00116 signal_finished_();
00117 }
00118
00119 void ThreadProgress::thread_function()
00120 {
00121 Glib::Rand rand;
00122 int usecs = 5000;
00123
00124 for(int i = 0; i < 100; ++i)
00125 {
00126 usecs = rand.get_int_range(std::max(0, usecs - 1000 - i), std::min(20000, usecs + 1000 + i));
00127 Glib::usleep(usecs);
00128
00129
00130 signal_increment_();
00131 }
00132 }
00133
00134 Application::Application()
00135 :
00136 main_loop_ (Glib::MainLoop::create())
00137 {
00138 std::cout << "Thread Dispatcher Example." << std::endl;
00139
00140 for(int i = 1; i <= 5; ++i)
00141 {
00142 ThreadProgress* progress=new ThreadProgress(i);
00143 progress_list_.push_back(progress);
00144 progress_ref_list_.push_back(Glib::RefPtr<ThreadProgress>(progress));
00145
00146 progress->signal_finished().connect(
00147 sigc::bind<1>(sigc::mem_fun(*this, &Application::on_progress_finished), progress));
00148 }
00149 }
00150
00151 Application::~Application()
00152 {
00153 }
00154
00155 void Application::launch_threads()
00156 {
00157 std::for_each(progress_list_.begin(), progress_list_.end(),
00158 std::mem_fun(&ThreadProgress::launch));
00159 }
00160
00161 void Application::run()
00162 {
00163 main_loop_->run();
00164 }
00165
00166 void Application::on_progress_finished(ThreadProgress* thread_progress)
00167 {
00168 {
00169 progress_list_.remove(thread_progress);
00170 thread_progress->join();
00171
00172 std::cout << "Thread " << thread_progress->id()
00173 << ": finished." << std::endl;
00174 }
00175
00176 if(progress_list_.empty())
00177 main_loop_->quit();
00178 }
00179
00180 }
00181
00182
00183 int main(int, char**)
00184 {
00185 Glib::thread_init();
00186
00187 Application application;
00188
00189
00190 Glib::signal_idle().connect(
00191 sigc::bind_return(sigc::mem_fun(application, &Application::launch_threads), false));
00192
00193 application.run();
00194
00195 return 0;
00196 }
00197