SharedBuffer: Refactor release() logic

We refactor this mildly in the hopes of making this a little easier
to follow for future readers.  We also go through the dealloc()
method so if we decide to invoke the SharedBuffer destructor in
the future, we only need to remember it in one place.

In addition, this is slightly more efficient in the multi-owner
case, since we no longer subtract to 0 and then (redundantly) set the
reference count explicitly to 0 as well.

Change-Id: Ifc773bd7900c89c36ac24904b2716f02cb57c095
This commit is contained in:
Greg Kaiser 2016-08-01 14:40:25 -07:00
parent 54cf81e61f
commit 476dbc48da
1 changed files with 17 additions and 7 deletions

View File

@ -111,16 +111,26 @@ void SharedBuffer::acquire() const {
int32_t SharedBuffer::release(uint32_t flags) const
{
int32_t prev = 1;
if (onlyOwner()
|| (((prev = mRefs.fetch_sub(1, std::memory_order_release)) == 1)
&& (atomic_thread_fence(std::memory_order_acquire), true))) {
const bool useDealloc = ((flags & eKeepStorage) == 0);
if (onlyOwner()) {
// Since we're the only owner, our reference count goes to zero.
mRefs.store(0, std::memory_order_relaxed);
if ((flags & eKeepStorage) == 0) {
free(const_cast<SharedBuffer*>(this));
if (useDealloc) {
dealloc(this);
}
// As the only owner, our previous reference count was 1.
return 1;
}
// There's multiple owners, we need to use an atomic decrement.
int32_t prevRefCount = mRefs.fetch_sub(1, std::memory_order_release);
if (prevRefCount == 1) {
// We're the last reference, we need the acquire fence.
atomic_thread_fence(std::memory_order_acquire);
if (useDealloc) {
dealloc(this);
}
}
return prev;
return prevRefCount;
}