Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2003-02-07 13:13:02


"William E. Kempf" <wekempf_at_[hidden]> writes:

> Dave Abrahams said:
>> On Thursday, February 06, 2003 12:33 PM [GMT+1=CET],
>> William E. Kempf <wekempf_at_[hidden]> wrote:
>>
> I didn't say it wasn't a result, I said that it wasn't "only" a result.
> In your case it's also the call.

OK.

>>> An asynchronous call can be bound to this result more than once.
>>
>> ...and if it can't be default-constructed?
>
> That's what boost::optional<> is for ;).

Yeeeh. Once the async_call returns, you have a value, and should be
able to count on it. You shouldn't get back an object whose invariant
allows there to be no value.

>>> 2) You're still hiding the thread creation.
>>
>> Absolutely. High-level vs. low-level.
>
> But I think too high-level. I say this, because it ties you solely
> to thread creation for asynchronous calls.

I understand your argument. I'm not suggesting we mask the low-level
interface.

>>> Second, and this is more important, you've bound this concept to
>>> boost::thread explicitly. With the fully seperated concerns of my
>>> proposal, async_result can be used with other asynchronous call
>>> mechanisms, such as the coming boost::thread_pool.
>>>
>>> asyc_result<double> res1, res2;

no fair - I'm calling it async_call now ;-)

>>> thread_pool pool;
>>> pool.dispatch(bind(res1.call(foo), a, b, c));
>>> pool.dispatch(bind(res2.call(foo), d, e, f));
>>> d = res1.value() + res2.value();
>>
>> This one is important. However, there are other ways to deal with this.
>> An async_call object could take an optional thread-creation parameter,
>> for example.
>
> It's not "thread-creation" in this case. You don't create threads
> when you use a thread_pool.

OK, "thread acquisition", then.

> And there's other examples as well, such as RPC mechanisms.

True.

> And personally, I find passing such a "creation parameter" to be
> turning the design inside out.

A bit, yes.

> It might make things a little simpler for the default case, but it
> complicates usage for all the other cases. With the design I
> presented every usage is treated the same.

There's a lot to be said for making "the default case" very easy.

> More importantly, if you really don't like the syntax of my design,
> it at least allows you to *trivially* implement your design.

I doubt most users regard anything involving typesafe varargs as
"trivial to implement."

> Sometimes there's something to be said for being "lower level".

Sometimes. I think users have complained all along that the
Boost.Threads library takes the "you can implement it yourself using
our primitives" line way too much. It's important to supply
simplifying high-level abstractions, especially in a domain as
complicated as threading.

>>> > That's what we mean by the terms "high-level" and "encapsulation"
>>> ;-)
>>>
>>> Yes, but encapsulation shouldn't hide the implementation to the point
>>> that users aren't aware of what the operations actually are. ;)
>>
>> I don't think I agree with you, if you mean that the implementation
>> should be apparent from looking at the usage. Implementation details
>> that must be revealed should be shown in the documentation.
>
> I was referring to the fact that you have no idea if the "async call" is
> being done via a thread, a thread_pool, an RPC mechanism, a simple message
> queue, etc. Sometimes you don't care, but often you do.

And for those cases you have a low-level interface, right?

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk