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@cs.fau.de