1 /* 2 * Copyright 2005 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdlib.h> 18 #include <string.h> 19 20 #include <cutils/atomic.h> 21 22 #include "SharedBuffer.h" 23 24 // --------------------------------------------------------------------------- 25 26 namespace android { 27 namespace tinyutils { 28 29 SharedBuffer* SharedBuffer::alloc(size_t size) 30 { 31 SharedBuffer* sb = static_cast<SharedBuffer *>(malloc(sizeof(SharedBuffer) + size)); 32 if (sb) { 33 sb->mRefs = 1; 34 sb->mSize = size; 35 } 36 return sb; 37 } 38 39 40 ssize_t SharedBuffer::dealloc(const SharedBuffer* released) 41 { 42 if (released->mRefs != 0) return -1; // XXX: invalid operation 43 free(const_cast<SharedBuffer*>(released)); 44 return 0; 45 } 46 47 SharedBuffer* SharedBuffer::edit() const 48 { 49 if (onlyOwner()) { 50 return const_cast<SharedBuffer*>(this); 51 } 52 SharedBuffer* sb = alloc(mSize); 53 if (sb) { 54 memcpy(sb->data(), data(), size()); 55 release(); 56 } 57 return sb; 58 } 59 60 SharedBuffer* SharedBuffer::editResize(size_t newSize) const 61 { 62 if (onlyOwner()) { 63 SharedBuffer* buf = const_cast<SharedBuffer*>(this); 64 if (buf->mSize == newSize) return buf; 65 buf = (SharedBuffer*)realloc(buf, sizeof(SharedBuffer) + newSize); 66 if (buf != NULL) { 67 buf->mSize = newSize; 68 return buf; 69 } 70 } 71 SharedBuffer* sb = alloc(newSize); 72 if (sb) { 73 const size_t mySize = mSize; 74 memcpy(sb->data(), data(), newSize < mySize ? newSize : mySize); 75 release(); 76 } 77 return sb; 78 } 79 80 SharedBuffer* SharedBuffer::attemptEdit() const 81 { 82 if (onlyOwner()) { 83 return const_cast<SharedBuffer*>(this); 84 } 85 return 0; 86 } 87 88 SharedBuffer* SharedBuffer::reset(size_t new_size) const 89 { 90 // cheap-o-reset. 91 SharedBuffer* sb = alloc(new_size); 92 if (sb) { 93 release(); 94 } 95 return sb; 96 } 97 98 void SharedBuffer::acquire() const { 99 android_atomic_inc(&mRefs); 100 } 101 102 int32_t SharedBuffer::release(uint32_t flags) const 103 { 104 int32_t prev = 1; 105 if (onlyOwner() || ((prev = android_atomic_dec(&mRefs)) == 1)) { 106 mRefs = 0; 107 if ((flags & eKeepStorage) == 0) { 108 free(const_cast<SharedBuffer*>(this)); 109 } 110 } 111 return prev; 112 } 113 114 } // namespace tinyutils 115 } // namespace android 116