|
Boost : |
From: Christopher Kohlhoff (chris_at_[hidden])
Date: 2007-03-12 09:30:39
Hi Braddock,
On Fri, 09 Mar 2007 09:05:42 -0500, "Braddock Gaskill"
<braddock_at_[hidden]> said:
> The ability to use a future with the asio::io_service in particular would
> be quite powerful.
I've attached a quick and dirty futures implementation that I wrote last
year to demonstrate how futures and asio might fit together. Unlike the
various futures proposals that are around, I prefer to keep the producer
and consumer interfaces separate. Hence I have promise<T> (producer
interface) and future<T> (consumer interface) -- these names are
borrowed from the Alice programming language.
Cheers,
Chris
#ifndef FUTURE_HPP
#define FUTURE_HPP
#include <memory>
#include <stdexcept>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
namespace detail {
template <typename T>
class return_value
{
public:
class exception_holder_base
{
public:
virtual ~exception_holder_base()
{
}
virtual void raise() const = 0;
};
template <typename E>
class exception_holder :
public exception_holder_base
{
public:
exception_holder(E e)
: e_(e)
{
}
virtual void raise() const
{
throw e_;
}
private:
E e_;
};
T get() const
{
boost::mutex::scoped_lock lock(mutex_);
while (!value_.get() && !exception_.get())
condition_.wait(lock);
if (exception_.get())
exception_->raise();
return *value_;
}
void set(T t)
{
boost::mutex::scoped_lock lock(mutex_);
if (value_.get() == 0 && exception_.get() == 0)
{
value_.reset(new T(t));
condition_.notify_all();
}
}
template <typename E>
void fail(E e)
{
boost::mutex::scoped_lock lock(mutex_);
if (value_.get() == 0 && exception_.get() == 0)
{
exception_.reset(new exception_holder<E>(e));
condition_.notify_all();
}
}
private:
mutable boost::mutex mutex_;
mutable boost::condition condition_;
std::auto_ptr<T> value_;
std::auto_ptr<exception_holder_base> exception_;
};
} // namespace detail
template <typename T>
class future;
template <typename T>
class promise
{
public:
promise()
: return_value_(new detail::return_value<T>)
{
}
void operator()(T t) // Fulfil
{
return_value_->set(t);
}
template <typename E>
void fail(E e)
{
return_value_->fail(e);
}
private:
friend class future<T>;
boost::shared_ptr<detail::return_value<T> > return_value_;
};
template <typename T>
class future
{
private:
public:
future(promise<T>& p)
: return_value_(p.return_value_)
{
}
T operator()() const // Await
{
return return_value_->get();
}
private:
boost::shared_ptr<detail::return_value<T> > return_value_;
};
#endif // FUTURE_HPP
#include <iostream>
#include <ostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include "future.hpp"
class Resolver
{
public:
Resolver() :
io_service_(),
work_(io_service_),
resolver_(io_service_),
thread_(boost::bind(&boost::asio::io_service::run, &io_service_))
{
}
~Resolver()
{
io_service_.stop();
thread_.join();
}
future<std::string> resolve(std::string host_name)
{
promise<std::string> result;
boost::asio::ip::tcp::resolver::query query(host_name, "0");
resolver_.async_resolve(query,
boost::bind(&Resolver::handle_resolve, this, _1, _2, result));
return result;
}
private:
void handle_resolve(boost::system::error_code ec,
boost::asio::ip::tcp::resolver::iterator iterator,
promise<std::string> result)
{
if (ec)
result.fail(boost::system::system_error(ec));
else
result(iterator->endpoint().address().to_string());
}
boost::asio::io_service io_service_;
boost::asio::io_service::work work_;
boost::asio::ip::tcp::resolver resolver_;
boost::thread thread_;
};
int main()
{
Resolver resolver;
future<std::string> result = resolver.resolve("www.boost.org");
std::cout << result() << "\n";
return 0;
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk