Kind of agree, and the root cause may be backwards compatibility so another construct is invented which is slightly different.
The other day I explored std::promise and std::future, only to realise that all it is under the hood is a semaphore (which starts with count of zero) and a pointer. The promise.set() updates the pointed memory and releases the semaphore, while future.get() waits for the semaphore and reads the memory. My workaround was just as many lines of code with abstractions that are no more complex. So whats the point of promise/futures? Async adds spawning a thread to the mix, yet another unneeded abstraction. Coroutine adds more. Just be done with this and add proper Actor model and call it a day.
The other day I explored std::promise and std::future, only to realise that all it is under the hood is a semaphore (which starts with count of zero) and a pointer. The promise.set() updates the pointed memory and releases the semaphore, while future.get() waits for the semaphore and reads the memory. My workaround was just as many lines of code with abstractions that are no more complex. So whats the point of promise/futures? Async adds spawning a thread to the mix, yet another unneeded abstraction. Coroutine adds more. Just be done with this and add proper Actor model and call it a day.