I strongly think we need to reconsider the design of this API from a usability perspective esspecially since almost all of our APIs are asychronous. If I have sometime I will look into what options we might have.
We have code like the following in several places in the streams and http_client product code:
After spending a couple of days looking into the product code where alloc/commit acquire/release is used it is very hard to write robust non leaking code. I’m really concerned about the usability of this API. Here is one example in the product code that is repeated all over the place. It will be very painful for us to try and fix up all these places.
```
const bool acquired = helper()->m_buffer.acquire(data, available);
if (available >= count)
{
auto buffer = m_helper->m_buffer;
auto post_write =
[buffer,data](pplx::task<size_t> op)-> pplx::task<size_t>
{
auto b = buffer;
b.release(data,op.get());
return op;
};
return target.putn(data, count).then(post_write);
}
```
In this case if the putn operation on the target buffer fails we will leave the buffer in an unknown state because the release won’t be executed.
We have code like the following in several places in the streams and http_client product code:
After spending a couple of days looking into the product code where alloc/commit acquire/release is used it is very hard to write robust non leaking code. I’m really concerned about the usability of this API. Here is one example in the product code that is repeated all over the place. It will be very painful for us to try and fix up all these places.
```
const bool acquired = helper()->m_buffer.acquire(data, available);
if (available >= count)
{
auto buffer = m_helper->m_buffer;
auto post_write =
[buffer,data](pplx::task<size_t> op)-> pplx::task<size_t>
{
auto b = buffer;
b.release(data,op.get());
return op;
};
return target.putn(data, count).then(post_write);
}
```
In this case if the putn operation on the target buffer fails we will leave the buffer in an unknown state because the release won’t be executed.