/*! \file
* \brief TODO.
*
* TODO. 
*
* Copyright (c) 2005-2007 Philipp Henkel
*
* Use, modification, and distribution are  subject to the
* Boost Software License, Version 1.0. (See accompanying  file
* LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
* http://threadpool.sourceforge.net
*
*/

#ifndef THREADPOOL_FUTURE_HPP_INCLUDED
#define THREADPOOL_FUTURE_HPP_INCLUDED


  
#include "./detail/future.hpp"
#include <boost/utility/enable_if.hpp>

//#include "pool.hpp"
//#include <boost/utility.hpp>

//#include <boost/thread/mutex.hpp>


namespace boost { namespace threadpool
{

  /*! \brief Experimental. Do not use in production code. TODO. 
  *
  * TODO Future
  *
  * \see TODO
  *
  */ 


template<class Result> 
class future
{
private:
  shared_ptr<detail::future_impl<Result> > m_impl;

public:
    typedef Result const & result_type; //!< Indicates the functor's result type.
    typedef Result future_result_type; //!< Indicates the future's result type.


public:

  future()
  : m_impl(new detail::future_impl<future_result_type>()) // TODO remove this
  {
  }

  // only for internal usage
  future(shared_ptr<detail::future_impl<Result> > const & impl)
  : m_impl(impl)
  {
  }

  bool ready() const
  {
    return m_impl->ready();
  }

  void wait() const
  {
    m_impl->wait();
  }

  bool timed_wait(boost::xtime const & timestamp) const
  {
    return m_impl->timed_wait(timestamp);
  }

   result_type operator()() // throw( thread::cancelation_exception, ... )
   {
     return (*m_impl)();
   }

   result_type get() // throw( thread::cancelation_exception, ... )
   {
     return (*m_impl)();
   }

   bool cancel()
   {
     return m_impl->cancel();
   }

   bool is_cancelled() const
   {
     return m_impl->is_cancelled();
   }
};





template<class Pool, class Function>
typename disable_if < 
  is_void< typename result_of< Function() >::type >,
  future< typename result_of< Function() >::type >
>::type
schedule(Pool& pool, const Function& task)
{
  typedef typename result_of< Function() >::type future_result_type;

  // create future impl and future
  shared_ptr<detail::future_impl<future_result_type> > impl(new detail::future_impl<future_result_type>);
  future <future_result_type> res(impl);

  // schedule future impl
  pool.schedule(detail::future_impl_task_func<detail::future_impl, Function>(task, impl));

  // return future
  return res;

/*
 TODO
  if(pool->schedule(bind(&Future::run, future)))
  {
    return future;
  }
  else
  {
    // construct empty future
    return error_future;
  }
  */
}



} } // namespace boost::threadpool

#endif // THREADPOOL_FUTURE_HPP_INCLUDED