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 <vector>
00017
00018 namespace
00019 {
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 class ThreadProgress
00030 {
00031 public:
00032 explicit ThreadProgress(int id);
00033 virtual ~ThreadProgress();
00034
00035 int id() const;
00036 void launch();
00037 void join();
00038 bool unfinished() const;
00039
00040 sigc::signal<void>& signal_finished();
00041
00042 private:
00043 enum { ITERATIONS = 100 };
00044
00045
00046
00047
00048 Glib::Thread* thread_;
00049 int id_;
00050 unsigned int progress_;
00051 Glib::Dispatcher signal_increment_;
00052 sigc::signal<void> signal_finished_;
00053
00054 void progress_increment();
00055 void thread_function();
00056 };
00057
00058 class Application : public sigc::trackable
00059 {
00060 public:
00061 Application();
00062 virtual ~Application();
00063
00064 void run();
00065
00066 private:
00067 Glib::RefPtr<Glib::MainLoop> main_loop_;
00068 std::vector<ThreadProgress*> progress_threads_;
00069
00070 void launch_threads();
00071 void on_progress_finished(ThreadProgress* thread_progress);
00072 };
00073
00074 template <class T>
00075 class DeletePtr : public std::unary_function<void, T>
00076 {
00077 public:
00078 void operator()(T ptr) const { delete ptr; }
00079 };
00080
00081 ThreadProgress::ThreadProgress(int id)
00082 :
00083 thread_ (0),
00084 id_ (id),
00085 progress_ (0)
00086 {
00087
00088 signal_increment_.connect(sigc::mem_fun(*this, &ThreadProgress::progress_increment));
00089 }
00090
00091 ThreadProgress::~ThreadProgress()
00092 {
00093
00094 g_return_if_fail(thread_ == 0);
00095 }
00096
00097 int ThreadProgress::id() const
00098 {
00099 return id_;
00100 }
00101
00102 void ThreadProgress::launch()
00103 {
00104
00105 thread_ = Glib::Thread::create(sigc::mem_fun(*this, &ThreadProgress::thread_function), true);
00106 }
00107
00108 void ThreadProgress::join()
00109 {
00110 thread_->join();
00111 thread_ = 0;
00112 }
00113
00114 bool ThreadProgress::unfinished() const
00115 {
00116 return (progress_ < ITERATIONS);
00117 }
00118
00119 sigc::signal<void>& ThreadProgress::signal_finished()
00120 {
00121 return signal_finished_;
00122 }
00123
00124 void ThreadProgress::progress_increment()
00125 {
00126 ++progress_;
00127 std::cout << "Thread " << id_ << ": " << progress_ << '%' << std::endl;
00128
00129 if (progress_ >= ITERATIONS)
00130 signal_finished_();
00131 }
00132
00133 void ThreadProgress::thread_function()
00134 {
00135 Glib::Rand rand;
00136
00137 for (int i = 0; i < ITERATIONS; ++i)
00138 {
00139 Glib::usleep(rand.get_int_range(2000, 20000));
00140
00141
00142 signal_increment_();
00143 }
00144 }
00145
00146 Application::Application()
00147 :
00148 main_loop_ (Glib::MainLoop::create()),
00149 progress_threads_ (5)
00150 {
00151
00152
00153
00154 #ifdef GLIBMM_EXCEPTIONS_ENABLED
00155 try
00156 #endif
00157 {
00158 for (std::vector<ThreadProgress*>::size_type i = 0; i < progress_threads_.size(); ++i)
00159 {
00160 ThreadProgress *const progress = new ThreadProgress(i + 1);
00161 progress_threads_[i] = progress;
00162
00163 progress->signal_finished().connect(
00164 sigc::bind<1>(sigc::mem_fun(*this, &Application::on_progress_finished), progress));
00165 }
00166 }
00167 #ifdef GLIBMM_EXCEPTIONS_ENABLED
00168 catch (...)
00169 {
00170
00171
00172 std::for_each(progress_threads_.begin(), progress_threads_.end(),
00173 DeletePtr<ThreadProgress*>());
00174 throw;
00175 }
00176 #endif
00177 }
00178
00179 Application::~Application()
00180 {
00181 std::for_each(progress_threads_.begin(), progress_threads_.end(),
00182 DeletePtr<ThreadProgress*>());
00183 }
00184
00185 void Application::run()
00186 {
00187
00188 Glib::signal_idle().connect(
00189 sigc::bind_return(sigc::mem_fun(*this, &Application::launch_threads), false));
00190
00191 main_loop_->run();
00192 }
00193
00194 void Application::launch_threads()
00195 {
00196 std::cout << "Launching " << progress_threads_.size() << " threads:" << std::endl;
00197
00198 std::for_each(progress_threads_.begin(), progress_threads_.end(),
00199 std::mem_fun(&ThreadProgress::launch));
00200 }
00201
00202 void Application::on_progress_finished(ThreadProgress* thread_progress)
00203 {
00204 thread_progress->join();
00205
00206 std::cout << "Thread " << thread_progress->id() << ": finished." << std::endl;
00207
00208
00209 if (std::find_if(progress_threads_.begin(), progress_threads_.end(),
00210 std::mem_fun(&ThreadProgress::unfinished)) == progress_threads_.end())
00211 {
00212 main_loop_->quit();
00213 }
00214 }
00215
00216 }
00217
00218 int main(int, char**)
00219 {
00220 Glib::thread_init();
00221
00222 Application application;
00223 application.run();
00224
00225 return 0;
00226 }