Boost logo

Boost :

Subject: Re: [boost] Futures
From: Thomas Heller (thom.heller_at_[hidden])
Date: 2015-01-13 10:52:35


On 01/12/2015 04:30 PM, Niall Douglas wrote:
> On 7 Jan 2015 at 12:40, Thomas Heller wrote:
>
>>> What is missing on POSIX is a portable universal kernel wait object
>>> used by everything in the system. It is correct to claim you can
>>> easily roll your own with a condition variable and an atomic, the
>>> problem comes in when one library (e.g. OpenCL) has one kernel wait
>>> object and another library has a slightly different one, and the two
>>> cannot be readily composed into a single wait_for_all() or
>>> wait_for_any() which accepts all wait object types, including
>>> non-kernel wait object types.
>>
>> Exactly, this could be easily achieved by defining an appropriate API for the
>> shared state of asynchronous operations, the wait functions would then just
>> use the async result objects, which in turn use to wait the functionality as
>> implemented in the shared state.
>
> You still seem to be assuming the existence of a shared state in wait
> objects :(

I absolutely do. Because I think it is inevitable. More on that below.

>
> I suppose it depends on how you define a shared state, but for that
> non-allocating design of mine the (a better name) "notification
> target" is the promise if get_future() has never been called, and the
> future if get_future() has ever been called. The notification target
> is kept by an atomic pointer, if he is set he points at a future
> somewhere, if he is null then either the promise is broken or the
> target is the promise.

Well, I think we have quite some misunderstanding here. I was using the
nomenclature as it is used in the standard. The standard talks about
asynchronous return objects (future and shared_future) and asynchronous
providers (promise, packaged_task, async). So yes, the future is a
notification target, and a promise is just one means to notify the
asynchronous return object (or notification target as you call it). The
shared state is therefor the communication channel connecting those two.
Non-allocating futures (and by implication non reference counted shared
states) have a major problem. I am basing my observation on your
proposal of basic_future and basic_promise (with my assumption to have
the nomenclature as in the standard). The problem is dangling pointers:
https://gist.github.com/sithhell/260796afcf11364eaf26
I can see that the problem 1 could get fixed easily by updating the
pointer the promise is pointing to ... but what about the second problem?

>
>> A portable, universal kernel wait object is
>> not really necessary for that.
>
> I think a portable, universal C API kernel wait object is very
> necessary if C++ is to style itself as a first tier systems
> programming language.
>
> We keep trivialising C compatibility, and we should not.

No one is trivialising C compatibility. You can call any C code from C++.

>
>> Not everyone wants to pay for the cost of a
>> kernel transition.
>
> You appear to assume a kernel transition is required.
>
> My POSIX permit object can CAS lock spin up to a certain limit before
> even considering to go acquire a kernel wait object at all, which I
> might add preferentially comes from a user side recycle list where
> possible. So if the wait period is very short, no kernel transition
> is required, indeed you don't even call malloc.
>
> That said, its design is highly limited to doing what it does because
> it has to make hard coded conservative assumptions about its
> surrounding environment. It can't support coroutines for example, and
> the fairness implementation does make it quite slow compared to a CAS
> lock because it can't know if fairness is important or not, so it
> must assume it is. Still, this is a price you need to pay if you want
> a C API which cannot take template specialisations.

So it is limited but generic? That doesn't make sense.

>
>> This is an implementation detail of a specific future
>> island, IMHO. Aside from that, i don't want to limit myself to POSIX.
>
> My POSIX permit object also works perfectly on Windows using the
> Windows condition variable API. And on Boost.Thread incidentally, I
> patch in the Boost.Thread condition_variable implementation. That
> gains me the thread cancellation emulation support in Boost.Thread
> and makes the boost::permit<> class fairly trivial to implement.

Please decide yourself what you want to call it ... is it POSIX now or
platform indepedent?
Is it C or C++? boost::permit<> looks pretty C++-ish to me.

-- 
Thomas Heller
Friedrich-Alexander-Universität Erlangen-Nürnberg
Department Informatik - Lehrstuhl Rechnerarchitektur
Martensstr. 3
91058 Erlangen
Tel.: 09131/85-27018
Fax:  09131/85-27912
Email: thomas.heller_at_[hidden]

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