On Tue, Oct 13, 2015 at 4:02 AM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 12/10/15 14:52, Hartmut Kaiser a écrit :
Sorry for cross-posting.
Vicente J. Botet Escriba wrote:
I have a branch (https://github.com/boostorg/thread/tree/feature/non_blocking_futures) that don't blocks on any future, but this will break async.
FWIW, the design decision to let those (and only those) futures block on destruction which are returned from async was one of the really bad decisions made for C++11, however that's just my opinion (others agree, but yet others disagree).
For what it is worth, I cannot figure out how to use future<> when the destructor blocks as it "breaks" most of my usecases. Then again just giving future a detach() member would solve it for me at least. We (as a community) really need a higher level, over-arching approach which
ties all of the above together! My plan is to work on a corresponding concept paper by the time of the committee meeting end of February 2016.
I plan to update the N4414 Executors and Schedulers Revision 5 proposal as I believe that Executors must be copyable and lightweight. The new proposal P0008R0 comes back to executors that are not copyable and so left the responsibility of the the lifetime to the user (I'm experimenting it in branch make_executors_copyable)
(disclaimer: I haven't had time to play with the branch just yet) I agree that making lifetime the problem of the user is not particularly nice. I'd prefer to split the executors interface where only the part which contains submit() is copyable and let the rest be non-copyable, we have successfully used a similar design internally (it makes the interface which is sent around and copied the smallest possible interface). See below for an incomplete and badly named example. /M // this code will not compile but hopefully you will be able to discern what it is supposed to do: class executor { // non-copyable public: typedef boost::work work; executor(executor const&) = delete; executor& operator=(executor const&) = delete; executor(); virtual ~executor() {}; virtual void close() = 0; virtual bool closed() = 0; // can probably be non-virtual executor_sink create_sink(); // for lack of better name virtual bool try_executing_one() = 0; template <typename Pred> bool reschedule_until(Pred const& pred); // not in the current interface virtual void loop() = 0; private: shared_ptr<something> _something; // given to executor_sink }; class executor_sink { // copyable public: typedef boost::work work; executor(shared_ptrexecutor::something); // public but only usable by executor because something is private executor_sink(executor_sink&) = default; executor_sink& operator=(const executor_sink&) = default; bool closed() const { if (auto shared_something = _something.lock()) return shared_something->closed(); return true; } bool submit(work&& w) { if (auto shared_something = _something.lock()) { shared_something->submit(w); return true; } return false; } private: weak_ptrexecutor::something _something; };