[cpp-threads] RE: "Agenda" for august 23-25 concurrency meeting

Peter Dimov pdimov at mmltd.net
Thu Aug 31 20:36:57 BST 2006


Howard Hinnant wrote:
> On Aug 31, 2006, at 1:34 PM, Peter Dimov wrote:
>
>> Howard Hinnant wrote:
>>
>>> The question I put before us, and strongly recommend that we answer
>>> positively is:
>>>
>>>     For asynchronous function calls, do we offer some mechanism for
>>> O (1) performance
>>>     of the return type as we do for synchronous function calls?
>>>
>>>     thread<vector<int> > t = launch_thread(bind(compute, input
>>> data));
>>>     vector<int> v = t();  // is this ridiculously expensive?
>>
>> Is
>>
>> future< vector<int> > fv = ex.execute( bind( compute, input data ) );
>> vector<int> v = fv.move(); // second move() or subsequent op()
>> throws value_already_moved
>>
>> good enough? It'd work for any asynchronous function call, not just
>> a dedicated thread, but the syntax is a bit clumsier (and the
>> implementation somewhat fragile but doable.)
>
> This design turns what I proposed to make a compile time error into a
> run time error.

I must be missing something.

thread<vector<int> > t = launch_thread(bind(compute, input_data));
vector<int> v = t();
vector<int> v2 = t(); // ?

How can you make the third line a compile-time error, but not the second?

> It also destroys efficiency for generic code getting
> an asynchronous value.
>
> template <class T, class Pred>
> void foo(Pred p)
> {
>    ...
>    T temp = p();  // if asynchronous, inefficiency mandated?
> // or:
>    T temp = p().move();  // No longer generic, Pred must be a future
>    ...
> }

Agreed... but...

template <class T, class Pred>
void foo(Pred p)
{
    ...
    T temp = p();
    T temp2 = p(); // ?
}

This code is fine when p is a future.

> One can never build efficient code on top of an inefficient base.  If
> there is no efficient layer in the threading API, then we have made
> the performance/feature tradeoff decision for all C++ clients in this
> area.  I'd far rather provide only an efficient base layer upon which
> clients can build their own feature-rich code, than provide only a
> feature-rich (but expensive) API.  If we can provide both layers,
> great (and I think we can).  But there is no question which layer is
> more important for us to provide (imho).

template<class R> class thread
{
private:

    future<R> ft_;

public:

    template<class F> explicit thread( F f )
    {
        ft_ = threaded_executor().execute( f );
    }

    R operator()()
    {
        return ft_.move();
    }
};

?

Also, the inefficiency does not manifest itself that often. If you have a

vector< thread< vector<int> > > v;

, fill it with async calls and then retrieve the return values in

vector< vector<int> > v2;

you only gain when you later need to operate on v2 in place. In the 
immutable case,

vector< future< vector<int> > > v;

(with the R const& return modification) is as efficient as the above, since 
the results are contained within the futures and there is no need to copy 
them out.

There's also the thread creation overhead that can easily dominate the 
vector<int> copy, but I'll be willing to assume for the sake of the argument 
that the underlying library pools the threads and the vectors are 
sufficienty large. :-)

I never explored the possibility of a noncopyable but movable future, by the 
way. 




More information about the cpp-threads mailing list