On Tue, Oct 13, 2015 at 7:48 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 13/10/15 10:39, Mikael Olenfalk a écrit :
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).
What you propose is something similar to the split in [p0113r0] where
there is an execution_context and executor_type.
I will take a closer look at [p0113r0] later tonight (what's up with the curious reference number, is there a system?).
However using shared_ptr as copyable ensures the lifetime issue, but I don't see the advantage in the split then.There is a problem with the shared_ptr approach that my current implementation in make_executors_copyable shares. The destructor of the shared state can be called in a thread that is part of the threads of the executor. That mean that the destructor must check if the thread to join is this thread and then not call the join.
I only use the shared_ptr internally in order to detect when the underlying executor is gone. In our code base we only use it to ensure that nobody posts to an executor after it has been destroyed (during shutdown). The split is "necessary" to hide the weak_ptr (because it is ugly) and in order to ensure that nobody accidentally uses a raw reference (the submit() function is gone from the executor). I hadn't even thought of the problem where the shared-state is destroyed in the wrong thread but you are obviously correct. Is it possible to come up with a design which does not have this problem?
In [p0113r0], the executor_context must outlive the executor_type copies that can be just references to the executor_context.
Personally I don't like such designs (where the user is required to ensure that something passed around by reference or raw pointer is kept alive between several threads and tasks and whatnots).
I don't see the need for the split in [p0113r0], as passing the executors by reference is equivalent.
I don't see it either (not yet at least - I will take a closer look).
So, do we want a design that force the user to ensure that the executor (execution_context) outlive the executor sinks (executor_type?
Please no.
Or, just a copyable executor?
How does that work when the actual underlying thingie (e.g. boost::asio::io_service) is non-copyable? Kind regards, Mikael