Boost logo

Boost Users :

Subject: [Boost-users] Waiting for a thread on another thread
From: Daniel Lidström (daniel.lidstrom_at_[hidden])
Date: 2010-03-05 10:22:19


Hello!

I have created a simple file logger using the active object pattern. This is intended to
offload logging operations to a separate thread, to not disturb the main thread with time-
consuming file operations. It works very nicely with boost::thread, but now I have a new
desired functionality. The file logger keeps an internal queue of strings that need to be
written to file. I want to know, from the main thread, when this queue is empty. To illustrate
I have created a minimal, hopefully compilable, sample that shows what I am trying to achieve.

#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
#include <boost/thread/condition.hpp>
#include <boost/foreach.hpp>
#include <boost/tr1/functional.hpp>
#include <vector>
#include <fstream>
#include <string>

class FileLogger
{
   typedef boost::unique_lock<boost::mutex> unique_lock;

   std::ofstream logfile;
   bool running;
   boost::thread running_thread;
   boost::mutex mutex;
   boost::condition_variable condition;
   std::vector<std::string> queue;

public:

   FileLogger(const std::string& filename)
      : logfile(filename.c_str())
      , running(true)
      , running_thread(std::tr1::bind(&FileLogger::Run, this))
   { }

   ~FileLogger()
   {
      running = false;
      condition.notify_one();
      running_thread.join();
   }

   void Log(const std::string& s)
   {
      unique_lock lock(mutex);
      queue.push_back(s);
   }

   void WaitForQueueFlush()
   {
      // ??
   }

private:

   void Run()
   {
      while( running ) {

         std::vector<std::string> copyList;
         {
            // wait 0.1 s here, for queue to fill up
            boost::xtime sleepTime;
            boost::xtime_get(&sleepTime, boost::TIME_UTC);
            sleepTime.nsec += 100*1000*1000;
            unique_lock lock(mutex);
            condition.timed_wait(lock, sleepTime);
            // fetch the current message list
            copyList.swap(queue);
         }
         BOOST_FOREACH(const std::string& s, copyList) {
            logfile << s << '\n';
         }
         logfile.flush();
      }
   }
};

int main()
{
   FileLogger fileLogger("logfile.txt");
   fileLogger.Log(std::string(1000*1000, '*'));
   // this call should wait, synchronously, until
   // current queue has been flushed to disk
   fileLogger.WaitForQueueFlush();
}

So the problem is to implement FileLogger::WaitForQueueFlush. How can I
signal the main thread when the queue has been emptied?

Thanks in advance!

Regards,

Daniel Lidström
Stockholm, Sweden


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net