|
View:
New views
20 Messages
—
Rating Filter:
Alert me
|
| < Prev | 1 - 2 - 3 - 4 - 5 | Next > |
|
|
Re: [futures] boost::futuresHi Braddock,
On Fri, 09 Mar 2007 09:05:42 -0500, "Braddock Gaskill" <braddock@...> 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; } _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futuresChristopher Kohlhoff wrote:
> 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. promise<> is an interesting name. The best with which I was able to come up so far was source<>. I also like the (obvious in hindsight) approach of making future<> constructible from promise<>. I was exploring something like pair< future<R>, source<R> > create_channel(); This does have the advantage that producers can only get a source/promise and consumers can only get a future, but I wasn't quite satisfied with it. To elaborate on Chris's point, the significance of keeping the producer and the consumer interface separate is that it allows future<R> to be made convertible to future<R2> whenever R is convertible to R2 (or R2 is void); this also allows extensions in the spirit of Frank Mori Hess's operator[], while still preserving the full generality of the producer (i.e. doesn't tie it to a specific executor). I didn't have time before the deadline to flesh out such a design, but if someone is willing and able to defend a similar proposal in Oxford, I will be glad to help with it. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futuresOn Sun, 11 Mar 2007 19:05:31 +0200, Peter Dimov wrote:
> N2185 does include a future<void> specialization. Oops, I can't believe I missed that. Great! -braddock _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futures> -----Original Message-----
> From: boost-bounces@... [mailto:boost-bounces@...] > On Behalf Of Christopher Kohlhoff > 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. Splitting promise from future seems like a good idea, it should make the future class in libpoet a little less confusing. One thing your code reminded me of is forwarding exceptions to the future, something I put off then completely forgot about in libpoet. Since I'm trying to provide an active function object that wraps an ordinary passive function, for the general case I would need to call something like your promise::fail() from a catch block that catches exceptions thrown by the passive function. Unfortunately, that would require something like a templated catch. It seems the best I can do is provide special handling for some particular type of exception, like a boost::shared_ptr<std::exception> and if the passive function throws anything else, it just gets forwarded to the future as something like a poet::unknown_exception. Frank _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futures> -----Original Message-----
> From: boost-bounces@... [mailto:boost-bounces@...] > On Behalf Of Peter Dimov > To elaborate on Chris's point, the significance of keeping the producer > and > the consumer interface separate is that it allows future<R> to be made > convertible to future<R2> whenever R is convertible to R2 (or R2 is void); > this also allows extensions in the spirit of Frank Mori Hess's operator[], Are you getting me confused with someone else? I don't remember any operator[]? One additional feature I am planning to add to libpoet is the ability to set a promise with a future. In terms of Chris's promise class, that would be something like a promise::operator()(const Future<T> &) This occurred to me while thinking about writing an active queue example program, where the queue would accept and return future<T> elements. Allowing a promise to be set with a future value would save having to poll the futures in the active queue object until they are ready to be used as values to fulfill promises. Frank _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futuresHess, Frank wrote:
>> To elaborate on Chris's point, the significance of keeping the producer >> and the consumer interface separate is that it allows future<R> to be >> made convertible to future<R2> whenever R is convertible to R2 (or >> R2 is void); this also allows extensions in the spirit of Frank Mori >> Hess's >> operator[], > > Are you getting me confused with someone else? I don't remember any > operator[]? I needed to go and check the archives; with so much independent development in this area it's easy to make attribution mistakes. My otherwise unreliable memory turned out to be correct in this case; in: http://lists.boost.org/Archives/boost/2007/03/117571.php you say: "You can do things like assign a Future<T> to a Future<U> if T is implicitly converible to U, without blocking. You can also extract elements from future containers and such, like getting a Future<int> from a Future<std::vector<int> > without blocking." Getting a Future<int> from Future< vector<int> > is an application of operator[], although I admit I don't know how it's expressed in your implementation. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futuresHess, Frank wrote:
> Splitting promise from future seems like a good idea, it should make > the future class in libpoet a little less confusing. One thing your > code reminded me of is forwarding exceptions to the future, something > I put > off then completely forgot about in libpoet. Since I'm trying to > provide an active function object that wraps an ordinary passive > function, for the general case I would need to call something like > your promise::fail() from a catch block that catches exceptions > thrown by the passive function. Unfortunately, that would require > something like a templated catch. It seems the best I can do is > provide special handling > for some particular type of exception, like a > boost::shared_ptr<std::exception> and if the passive function throws > anything else, it just gets forwarded to the future as something like > a poet::unknown_exception. This won't be a problem in the next C++ if N2179 passes: http://www.pdimov.com/cpp/N2179.html My implementation provides a partial emulation of N2179: http://www.pdimov.com/cpp/N2179/exception_ptr.hpp http://www.pdimov.com/cpp/N2179/exception_ptr.cpp _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futures-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1 On Monday 12 March 2007 15:32 pm, Peter Dimov wrote: > This won't be a problem in the next C++ if N2179 passes: > > http://www.pdimov.com/cpp/N2179.html > > My implementation provides a partial emulation of N2179: > > http://www.pdimov.com/cpp/N2179/exception_ptr.hpp > http://www.pdimov.com/cpp/N2179/exception_ptr.cpp Yes, that's just what I was looking for. I didn't see any license specified on your implementation though. Is is all right for me to copy your implementation into a boost-licenced library? Also, it would be nice if the top-level webpage on your site had a way to navigate down to your exception_ptr and future proposals (or am I just missing it?). - -- Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) iD8DBQFF9boL5vihyNWuA4URAkLrAJ9UyFGuXs73lcek0iPRdMNcU0h81ACcCc2a R2DryUyiNEDyrRleu1e3FDk= =+yJl -----END PGP SIGNATURE----- _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futuresOn Tue, 13 Mar 2007 00:30:39 +1100, Christopher Kohlhoff wrote:
> 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 Okay, this got me thinking. A weakness in the future<> concept, as I understand it, is that if a future is never set(), then the invoking thread can hang waiting for it. Not very RAII. The situation is much improved if future<T> and promise<T> are split, and promise<T> is reference counted. If the last promise<T> for a particular future<T> goes out of scope, than any thread waiting on the matching future<T> would be failed with a promise_broken exception or somesuch. Is this already part of the promise<T> concept? Braddock Gaskill Dockside Vision Inc _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futures-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1 On Monday 12 March 2007 17:12 pm, Braddock Gaskill wrote: > A weakness in the future<> concept, as I understand it, is that if a > future is never set(), then the invoking thread can hang waiting for it. > Not very RAII. > > The situation is much improved if future<T> and promise<T> are split, > and promise<T> is reference counted. If the last promise<T> for a > particular future<T> goes out of scope, than any thread waiting on the > matching future<T> would be failed with a promise_broken exception or > somesuch. > > Is this already part of the promise<T> concept? No, at least it wasn't in the code Chris posted. I like the idea though, thanks. I'm going to incorporate it into my code. - -- Frank -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) iD8DBQFF9cVJ5vihyNWuA4URAgLtAKCqOsWWx22RmRjofDcN0/SKM5/yiwCgtmYz ysMas3e+R2ifsMAJTzYaP6I= =aY5Z -----END PGP SIGNATURE----- _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futuresOn Mon, 12 Mar 2007 16:38:42 +0200, "Peter Dimov" <pdimov@...> said: > To elaborate on Chris's point, the significance of keeping the producer > and > the consumer interface separate is that it allows future<R> to be made > convertible to future<R2> whenever R is convertible to R2 (or R2 is > void); Are there any implications for the ability for movability of the result if you allow such conversions? Cheers, Chris _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futuresOn Mon, 12 Mar 2007 17:25:27 -0400, "Frank Mori Hess" <frank.hess@...> said: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > On Monday 12 March 2007 17:12 pm, Braddock Gaskill wrote: > > A weakness in the future<> concept, as I understand it, is that if a > > future is never set(), then the invoking thread can hang waiting for it. > > Not very RAII. > > > > The situation is much improved if future<T> and promise<T> are split, > > and promise<T> is reference counted. If the last promise<T> for a > > particular future<T> goes out of scope, than any thread waiting on the > > matching future<T> would be failed with a promise_broken exception or > > somesuch. > > > > Is this already part of the promise<T> concept? > > No, at least it wasn't in the code Chris posted. I like the idea though, > thanks. I'm going to incorporate it into my code. I agree, it's an excellent idea. I think it would be more idiomatic to name the exception "broken_promise" though :) Cheers, Chris _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futuresFrank Mori Hess wrote:
> -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > On Monday 12 March 2007 15:32 pm, Peter Dimov wrote: >> This won't be a problem in the next C++ if N2179 passes: >> >> http://www.pdimov.com/cpp/N2179.html >> >> My implementation provides a partial emulation of N2179: >> >> http://www.pdimov.com/cpp/N2179/exception_ptr.hpp >> http://www.pdimov.com/cpp/N2179/exception_ptr.cpp > > Yes, that's just what I was looking for. I didn't see any license > specified on your implementation though. Is is all right for me to > copy > your implementation into a boost-licenced library? Also, it would be > nice > if the top-level webpage on your site had a way to navigate down to > your exception_ptr and future proposals (or am I just missing it?). I will update the files to use the Boost license in a few days (and will link to the papers from the front page as soon as the mailing is made officially available on the committee web site). _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futuresI've made a futures implementation in the hopes of combining the best features
from all the proposals and various implementations currently floating around. It is still rough around the edges, but is mostly covered by unit tests. http://braddock.com/~braddock/future/ I'm looking for input. I'd be willing to add additional functionality needed and progress it to the point where it could be formally submitted into boost if there is interest. It could perhaps be merged into the existing futures implementation in the vault to add combined groups, etc. I used Peter's exception_ptr code, which he said he would post under a boost license. -Braddock Gaskill Below are the README comments: GOAL: Provide a definitive future implementation with the best features of the numerous implementations and proposals floating around, in the hopes to avoid multiple incompatible future implementations (coroutines, active objects, asio, etc). Also, to explore the combined implementation of the best future concepts. FEATURES: -split promise<T>/future<T> concept. -Agnostic to scheduling, any active object implementation, thread model, etc etc. Basic future which can be used in many contexts. -promise<T> is reference counted - if the last promise<T> goes out of scope before the future is set, the future is automatically failed with a broken_promise exception. -add_callback() permits arbitrary functions to be called when the future is set. This is needed to build non-intrusive compound waiting structures, like future_groups, or to better support continuation scheduling concepts, as in coroutines. -Value type does not require a default constructor, and no wasteful excess default construction is performed. Value type only needs to be copy constructable. -set_cancel_handler() permits an arbitrary function to be called to cancel the future, if possible. -atomic set_or_throw() permits the caller to detect if a set was successful (ie, if the caller was the first to transition the future to ready). This enables promise/future to be used to as a type of atomic semaphore. -future<void> and promise<void> specializations, as per Dimov proposal -Pass-by-reference specializations, such as future<int&>, permit return by reference, as per Dimov proposal. -Uses Peter Dimov's exception_ptr implementation to make a best-effort to pass exception types between threads. -implementation of all three of f, f(), an f.get() blocking accessor syntaxes, for better or for worse. TODO: The following class of sub-type assignments should be made possible, as discussed by Frank Hess and Peter Dimov on the list. class A {}; class B : public A {}; promise<shared_ptr<B> > p; future<shared_ptr<A> > f(p); future_group classes and simple function wrappers should be provided, although kept seperate from the main future<T> implementation. RATIONALE: Some method names were reverted to Peter Dimov's earlier N2096 proposal because of better semantics, in the author's opinion. set_value() -> set() - primary use of future join() -> wait() - more descriptive, less thread-centric timed_join() -> timed_wait() try_join() -> ready() - join implies blocking, but this returns state The user-supplied cancel_handler is called after the future/promise is unlocked. Otherwise, the cancel_handler could cause a deadlock if it invokes any methods upon the promise/future. This means that worker threads COULD call set() upon a canceled future, but these calls would be ignored. This is (IMHO) correct behavior. A cancel() invocation sets the future's state with a future_cancel exception - it does not guarantee that the work is actually canceled, because in many cases it cannot be stopped. -Should set() silently ignore calls on an already set promise, or should it throw? Peter Dimov's proposal says ignore, and I'm inclined to agree because if a user sets up a scenario where a promise is shared between multiple functions, or where a future is canceled, it is impossible for the author of the individual function to foresee the exceptional situation. I offer set_or_throw() to still allow use of future for atomic signaling. REFERENCES: Transporting Values and Exceptions between Threads N2096, Peter Dimov http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2096.html Proposed Text for Parallel Task Execution, Peter Dimov (DRAFT) http://www.pdimov.com/cpp/N2185.html Multithreading API for C++0X - A Layered Approach, Howard Hinnant http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2027.html Concur and C++ Futures, Herb Sutter, presentation video & slides http://video.google.com/videoplay?docid=7625918717318948700 http://www.nwcpp.org/Downloads/2006/The_Concur_Project_-_NWCPP.pdf Language Support for Transporting Exceptions Between Threads N2179, Peter Dimov http://www.pdimov.com/cpp/N2179.html Active Object libpoet framework by Frank Mori Hess http://source.emptycrate.com/projects/activeobjects/ http://www.comedi.org/projects/libpoet/index.html Boost Coroutine library Boost Vault future library Chris Kohlhoff's future implementation, posted to boost-devel list Enjoy, Braddock Gaskill Dockside Vision inc _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futuresHello,
> I've made a futures implementation in the hopes of combining > the best features from all the proposals and various > implementations currently floating around. It is still rough > around the edges, but is mostly covered by unit tests. > > http://braddock.com/~braddock/future/ In your implementation I'm missing operators for logical combination of futures like it is supported by the futures implementation of Thorsten Schütt (vault files). Oliver _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futuresOn Wed, 14 Mar 2007 06:49:57 +0100, Oliver.Kowalke wrote:
>> I've made a futures implementation in the hopes of combining >> http://braddock.com/~braddock/future/ > > In your implementation I'm missing operators for logical combination of > futures like it is supported by the futures implementation of Thorsten Schütt > (vault files). Hi Oliver, Yes, I would like to either add this, or merge into Schutt's implementation if he is interested. And example of an unintrusive operator||() is below. I added a public add_callback() method which calls an observer function when the future's state changes. This should allow grouping of futures or combined waits to be handled unintrusively outside of the main future classes. This public observer method is also needed for things like future-aware task scheduling (like Frank Hess's draft active object or boost::coroutine). template <typename T> struct future_or { future_or(future<T> &a, future<T> &b) : a_(a), b_(b) {} future_or(const future_or &f) : a_(f.a_), b_(f.b_), p_(f.p_) {} struct future_or_failed : public std::exception { }; void operator()() { boost::mutex::scoped_lock lck(mutex_); if (a_.has_value()) p_.set(a_.get()); else if (b_.has_value()) p_.set(b_.get()); else if (a_.has_exception() && b_.has_exception()) // both failed p_.set_exception(future_or_failed()); } future<T> a_,b_; promise<T> p_; boost::mutex mutex_; }; template<typename T> future<T> operator||(future<T> &a, future<T> &b) { future_or<T> fa(a, b); a.add_callback(fa); return fa.p_; } void TestCase7() { // test future or || example promise<int> p1; promise<int> p2; future<int> f1(p1); future<int> f2(p2); future<int> f1_or_f2 = f1 || f2; BOOST_CHECK(!f1_or_f2.ready()); p1.set(97); p2.set(-5); // will be ignored by the or BOOST_CHECK(f1_or_f2.ready()); BOOST_CHECK_EQUAL(f1_or_f2.get(), 97); } _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futures> On Wednesday, March 14, 2007 12:44 PM, Braddock Gaskill wrote: > >> I've made a futures implementation in the hopes of combining > >> http://braddock.com/~braddock/future/ > > > > In your implementation I'm missing operators for logical > combination > > of futures like it is supported by the futures implementation of > > Thorsten Schütt (vault files). > > Hi Oliver, > Yes, I would like to either add this, or merge into Schutt's > implementation if he is interested. And example of an > unintrusive operator||() is below. <snip> Looks good for me - so could the other members agree to Braddocks implementation in order to have one base for futhur development/evolution of the futures concept? Oliver _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
|
|
|
Re: [futures] boost::futures> On Wednesday, March 14, 2007 12:44 PM, Braddock Gaskill wrote: > >> I've made a futures implementation in the hopes of combining > >> http://braddock.com/~braddock/future/ > > > > In your implementation I'm missing operators for logical > combination > > of futures like it is supported by the futures implementation of > > Thorsten Schütt (vault files). > > Hi Oliver, > Yes, I would like to either add this, or merge into Schutt's > implementation if he is interested. And example of an > unintrusive operator||() is below. <snip> Looks good for me - so could the other members agree to Braddocks implementation in order to have one base for further development/evolution of the futures concept? Oliver _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
|
|
Re: [futures] boost::futuresOn Wed, 14 Mar 2007 07:43:47 -0400, Braddock Gaskill wrote:
> And example of an unintrusive operator||() is below. > template<typename T> > future<T> operator||(future<T> &a, future<T> &b) { > future_or<T> fa(a, b); > a.add_callback(fa); > return fa.p_; > } Minor bug in the code I just posted, I left out b.add_callback(fa) in here. Are there any thoughts on how && and || operators should properly handle exceptions? _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost |
| < Prev | 1 - 2 - 3 - 4 - 5 | Next > |
| Free embeddable forum powered by Nabble | Forum Help |