#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <vector>

struct worker
{
  worker(boost::condition* sig)
    :done_flag(false)
    ,done_sig(sig)
    ,thread(boost::bind(&worker::go,boost::ref(*this)))
  {}
  ~worker()
  {
    thread.join();
  }
  void go()
  {
    for (int i=10;i>=0;i--) {
      sleep(1);
      std::cerr << ".";
    }
    done_flag=true;
    done_sig->notify_one();
  }
  volatile bool done_flag;
  boost::condition*const done_sig;
  boost::thread thread;
};

void threadmaster(volatile bool* work_request,boost::condition* condition,volatile bool* all_done)
{
  std::vector<worker*> workers;
  boost::mutex mutex;
  boost::mutex::scoped_lock lock(mutex);
  for (;;)
    {
      if (*work_request) {
	workers.push_back(new worker(condition));
	*work_request=false;
	std::cerr << "+";
      }

      std::vector<worker*>::iterator it=workers.begin();
      while (it!=workers.end())
	{
	  if ((*it)->done_flag) {
	    delete (*it);
	    workers.erase(it);
	    std::cerr << "-";
	  } else {
	    it++;
	  }
	}
      
      std::cerr << "[" << workers.size() << "]";
      if (workers.empty()) break;
      
      condition->wait(lock);
    }

  std::cerr << "[All done.  Bye.]";
  *all_done=true;
}

int main(int,char**)
{
  volatile bool work_request=true;
  volatile bool all_done=false;
  boost::condition condition;
  boost::thread thread(boost::bind(threadmaster,&work_request,&condition,&all_done));
  for (;;)
    {
      const int c=getc(stdin);
      if (c==EOF || all_done) break;
      std::cerr << "!";
      work_request=true;
      condition.notify_one();
    }
  std::cerr << "[That's all]\n";
  return 0;
}

