Ok, I think I see where you're coming from here. I've replied to
some points below just to make sure and discuss possible
solutions.
On Thursday, 4 October 2012 at 16:07:35 UTC, David Nadlinger
wrote:
On Wednesday, 3 October 2012 at 23:02:25 UTC, dsimcha wrote:
Because you already have a system in place for managing these
tasks, which is separate from std.parallelism. A reason for
this could be that you are using a third-party library like
libevent. Another could be that the type of workload requires
additional problem knowledge of the scheduler so that different
tasks don't tread on each others's toes (for example
communicating with some servers via a pool of sockets, where
you can handle several concurrent requests to different
servers, but can't have two task read/write to the same socket
at the same time, because you'd just send garbage).
Really, this issue is just about extensibility and/or
flexibility. The design of std.parallelism.Task assumes that
all values which "becomes available at some point in the
future" are the product of a process for which a TaskPool is a
suitable scheduler. C++ has std::future separate from
std::promise, C# has Task vs. TaskCompletionSource, etc.
I'll look into these when I have more time, but I guess what it
boils down to is the need to separate the **abstraction** of
something that returns a value later (I'll call that
**abstraction** futures) from the **implementation** provided by
std.parallelism (I'll call this **implementation** tasks), which
was designed only with CPU-bound tasks and multicore in mind.
On the other hand, I like std.parallelism's simplicity for
handling its charter of CPU-bound problems and multicore
parallelism. Perhaps the solution is to define another Phobos
module that models the **abstraction** of futures and provide an
adapter of some kind to make std.parallelism tasks, which are a
much lower-level concept, fit this model. I don't think the
**general abstraction** of a future should be defined in
std.parallelism, though. std.parallelism includes
parallelism-oriented things besides tasks, e.g. parallel map,
reduce, foreach. Including a more abstract model of values that
become available later would make its charter too unfocused.
Maybe using the word "callback" was a bit misleading, but it
callback would be invoked on the worker thread (or by whoever
invokes the hypothetical Future.complete(<result>) method).
Probably most trivial use case would be to set a condition
variable in it in order to implement a waitAny(Task[]) method,
which waits until the first of a set of tasks is completed.
Ever wanted to wait on multiple condition variables? Or used
select() with multiple sockets? This is what I mean.
Well, implementing something like ContinueWith or Future.complete
for std.parallelism tasks would be trivial, and I see how waitAny
could easily be implemented in terms of this. I'm not sure I
want to define an API for this in std.parallelism, though, until
we have something like a std.future and the **abstraction** of a
future is better-defined.
For more advanced/application-level use cases, just look at any
use of ContinueWith in C#. std::future::then() is also proposed
for C++, see e.g.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3327.pdf.
I didn't really read the the N3327 paper in detail, but from a
brief look it seems to be a nice summary of what you might want
to do with tasks/asynchronous results – I think you could
find it an interesting read.
I don't have time to look at these right now, but I'll definitely
look at them sometime soon. Thanks for the info.