
#ifndef _Future_HH_INCLUDED_
#define	_Future_HH_INCLUDED_

#include <boost/thread.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

namespace bneijt
{
template<typename ReturnType>
class Future
{
    boost::function0< ReturnType > d_function; ///< Target function
    ReturnType d_result; ///< Result value, users are encouraged to use shared_ptr
    boost::condition d_finished;///< Event to queue for the finish of it
    boost::mutex d_working;
    bool d_done;
    boost::thread *d_thread;
	public:
	  Future(
	    boost::function0< ReturnType > f//Function to call
	    //Arguments for the function (vargs)
	    )
	   :
	   d_function(f),
	   d_result(),
	   d_finished(),
	   d_working(),
	   d_done(false),
	   d_thread()
	  {
  	  //Call the function in another thread
  	  d_thread = new boost::thread(boost::bind(&Future::run, this));
	  }
	  ~Future()
	  {
	    delete d_thread;
	  }
	  
	  ReturnType operator()()
	  {
	    //Wait for finish event
      boost::mutex::scoped_lock lk(d_working);
	    while(!d_done)
	      d_finished.wait(lk);

	    //Return result
	    return d_result;
	  }
  private:
	  void run()
	  {
	    //Call the function
	    d_result = d_function();
	    //Update done
	    {
	      //Lock class, 
	      boost::mutex::scoped_lock lock(d_working);
	      d_done = true;
  	    //Unlock class
	    }
	    //Hit the event button
	    d_finished.notify_one();
	  }
};
} //Namespace
#endif


