#include <glibmm.h>
 
 
namespace
{
 
class ThreadProgress
{
public:
  explicit ThreadProgress(int the_id);
  ~ThreadProgress();
 
  int id() const;
  void join();
  bool unfinished() const;
 
 
private:
  enum
  {
    ITERATIONS = 100
  };
 
  
  
  
  int id_;
  unsigned int progress_;
 
  void progress_increment();
  void thread_function();
};
 
{
public:
  Application();
  ~Application();
 
  void run();
 
private:
 
  void launch_threads();
  void on_progress_finished(ThreadProgress* thread_progress);
};
 
template <class T>
class DeletePtr
{
  typedef void argument_type;
  typedef T result_type;
public:
  void operator()(T ptr) const { delete ptr; }
};
 
ThreadProgress::ThreadProgress(int the_id) : thread_(nullptr), id_(the_id), progress_(0)
{
  
  signal_increment_.connect(
sigc::mem_fun(*
this, &ThreadProgress::progress_increment));
}
 
ThreadProgress::~ThreadProgress()
{
  
  g_return_if_fail(thread_ == nullptr);
}
 
int
ThreadProgress::id() const
{
  return id_;
}
 
void
ThreadProgress::launch()
{
  
  thread_ = 
new std::thread([
this]() { thread_function(); });
}
 
void
ThreadProgress::join()
{
  thread_->join();
  delete thread_;
  thread_ = nullptr;
}
 
bool
ThreadProgress::unfinished() const
{
  return (progress_ < ITERATIONS);
}
 
ThreadProgress::signal_finished()
{
  return signal_finished_;
}
 
void
ThreadProgress::progress_increment()
{
  ++progress_;
 
  if (progress_ >= ITERATIONS)
    signal_finished_();
}
 
void
ThreadProgress::thread_function()
{
 
  for (auto i = 0; i < ITERATIONS; ++i)
  {
 
    
    signal_increment_();
  }
}
 
{
  try
  {
    {
      ThreadProgress* const progress = new ThreadProgress(i + 1);
      progress_threads_[i] = progress;
 
      progress->signal_finished().connect(
    }
  }
  catch (...)
  {
    
    
    std::for_each(progress_threads_.begin(), progress_threads_.end(), DeletePtr<ThreadProgress*>());
 
    throw;
  }
}
 
Application::~Application()
{
  std::for_each(progress_threads_.begin(), progress_threads_.end(), DeletePtr<ThreadProgress*>());
 
}
 
void
Application::run()
{
  
 
  main_loop_->run();
}
 
void
Application::launch_threads()
{
 
    progress_threads_.begin(), progress_threads_.end(), 
std::mem_fn(&ThreadProgress::launch));
}
 
void
Application::on_progress_finished(ThreadProgress* thread_progress)
{
  thread_progress->join();
 
 
  
  if (
std::find_if(progress_threads_.begin(), progress_threads_.end(),
 
        std::mem_fn(&ThreadProgress::unfinished)) == progress_threads_.end())
 
  {
    main_loop_->quit();
  }
}
 
} 
 
int
main(int, char**)
{
 
  Application application;
  application.run();
 
  return 0;
}
constexpr _InputIterator find_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
constexpr _Function for_each(_InputIterator __first, _InputIterator __last, _Function __f)
constexpr _Mem_fn< _Tp _Class::* > mem_fn(_Tp _Class::*__pm) noexcept
basic_ostream< _CharT, _Traits > & endl(basic_ostream< _CharT, _Traits > &__os)
constexpr size_type size() const noexcept
Signal class for inter-thread communication.
Definition dispatcher.h:66
static Glib::RefPtr< MainLoop > create(bool is_running=false)
gint32 get_int_range(gint32 begin, gint32 end)
void connect_once(const sigc::slot< void()> &slot, int priority=PRIORITY_DEFAULT_IDLE)
Connects an idle handler that runs only once.
SignalIdle signal_idle()
Convenience idle signal.
decltype(auto) bind(const T_functor &func, T_bound... b)
decltype(auto) mem_fun(T_obj &obj, T_return(T_obj2::*func)(T_arg...))
void usleep(unsigned long microseconds)
Pauses the current thread for the given number of microseconds.
void init()
Initialize glibmm.