SharedBuffer* SharedBuffer::attemptEdit() const { if (onlyOwner()) { return const_cast<SharedBuffer*>(this); } return 0; }
int32_t SharedBuffer::release(uint32_t flags) const { int32_t prev = 1; if (onlyOwner() || ((prev = android_atomic_dec(&mRefs)) == 1)) { mRefs = 0; if ((flags & eKeepStorage) == 0) { free(const_cast<SharedBuffer*>(this)); } } return prev; }
SharedBuffer* SharedBuffer::edit() const { if (onlyOwner()) { return const_cast<SharedBuffer*>(this); } SharedBuffer* sb = alloc(mSize); if (sb) { memcpy(sb->data(), data(), size()); release(); } return sb; }
SharedBuffer* SharedBuffer::editResize(size_t newSize) const { if (onlyOwner()) { SharedBuffer* buf = const_cast<SharedBuffer*>(this); if (buf->mSize == newSize) return buf; buf = (SharedBuffer*)realloc(buf, sizeof(SharedBuffer) + newSize); if (buf != NULL) { buf->mSize = newSize; return buf; } } SharedBuffer* sb = alloc(newSize); if (sb) { const size_t mySize = mSize; memcpy(sb->data(), data(), newSize < mySize ? newSize : mySize); release(); } return sb; }
int32_t SharedBuffer::release(uint32_t flags) const { 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 (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 prevRefCount; }
SharedBuffer* SharedBuffer::editResize(size_t newSize) const { if (onlyOwner()) { SharedBuffer* buf = const_cast<SharedBuffer*>(this); if (buf->mSize == newSize) return buf; // Don't overflow if the combined size of the new buffer / header is larger than // size_max. LOG_ALWAYS_FATAL_IF((newSize >= (SIZE_MAX - sizeof(SharedBuffer))), "Invalid buffer size %zu", newSize); buf = (SharedBuffer*)realloc(buf, sizeof(SharedBuffer) + newSize); if (buf != NULL) { buf->mSize = newSize; return buf; } } SharedBuffer* sb = alloc(newSize); if (sb) { const size_t mySize = mSize; memcpy(sb->data(), data(), newSize < mySize ? newSize : mySize); release(); } return sb; }