Boost logo

Boost :

From: William E. Kempf (wekempf_at_[hidden])
Date: 2003-02-05 16:02:02


>
> Hi Ove,
>
>> f. It shall be possible to send extra information, as an optional
>> extra argument
>> to the boost::thread ctor, to the created thread.
>> boost::thread::self shall offer a method for retrieving this extra
>> information. It is not required that this information be passed in
>> a type-safe manner, i.e. void* is okay.
>>
>> g. It shall be possible for a thread to exit with a return value.
>> It shall be
>> possible for the creating side to retrieve, as a return value
>> from join(), that value. It is not required that this value be
>> passed in a type-safe manner, i.e. void* is okay.
>>
>> j. The header file shall not expose any implementation specific
>> details.
>
> Incidentally, I have a scheme almost ready that does all this. In
> particular, it allows you to pass every number of parameters to the new
> thread, and to return every possible type. Both happens in a type-safe
> fashion, i.e. whereever you would call a function serially like
> double d = foo(a, b, c);
> you can now call it like
> double d;
> thread<double> t = spawn(foo)(a,b,c);
> // do something else
> d = thread.return_value();

A solution like this has been proposed before, but I don't like it. This
creates multiple thread types, instead of a single thread type. I think
this will only make the interface less convenient, and will make the
implementation much more complex. For instance, you now must have a
seperate thread_self type that duplicates all of thread<> except for the
data type specific features. These differing types will have to compare
to each other, however.

I don't feel that this sort of information belongs in the thread object.
It belongs in the thread function. This already works very nicely for
passing data, we just need some help with returning data. And I'm working
on that. The current idea would be used something like this:

async_result<double> res;
thread t(bind(res.call(), a, b, c));
// do something else
d = res.value(); // Explicitly waits for the thread to return a value?

Now thread remains type-neutral, but we have the full ability to both pass
and return values in a type-safe manner.

> Argument and return types are automatically deducted, and the number of
> arguments are only limited by the present restriction on the number of
> elements in boost::tuple (which I guess is 10). Conversions between
> types are performed in exactly the same way as they would when calling
> a function serially. Furthermore, it also allows calling member
> functions with some object, without the additional syntax necessary to
> tie object and member function pointer together.

Hopefully you're not duplicating efforts here, and are using Boost.Bind
and Boost.Function in the implementation?

> I attach an almost ready proposal to this mail, but rather than
> steamrolling the present author of the threads code (William Kempf), I
> would like to discuss this with him (and you, if you like) before
> submitting it as a proposal to boost.

Give me a couple of days to have the solution above implemented in the dev
branch, and then argue for or against the two designs.

> Let me add that I agree with all your other topics, in particular the
> separation of calling/called thread interface, to prevent accidents like
> thread<> t = spawn(foo)(a,b,c);
> t.yield (); // oops, who's going to yield here?

You shouldn't really ever write code like that. It should be
thread::yield(). But even if you write it the way you did, it will always
be the current thread that yields, which is the only thread that can. I
don't agree with seperating the interfaces here.

> I would be most happy if we could cooperate and join efforts.

Certainly.

-- 
William E. Kempf
wekempf_at_[hidden]

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