Home | History | Annotate | Download | only in libutils
      1 /*
      2  * Copyright (C) 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 <utils/SharedBuffer.h>
     21 #include <utils/Atomic.h>
     22 
     23 // ---------------------------------------------------------------------------
     24 
     25 namespace android {
     26 
     27 SharedBuffer* SharedBuffer::alloc(size_t size)
     28 {
     29     SharedBuffer* sb = static_cast<SharedBuffer *>(malloc(sizeof(SharedBuffer) + size));
     30     if (sb) {
     31         sb->mRefs = 1;
     32         sb->mSize = size;
     33     }
     34     return sb;
     35 }
     36 
     37 
     38 ssize_t SharedBuffer::dealloc(const SharedBuffer* released)
     39 {
     40     if (released->mRefs != 0) return -1; // XXX: invalid operation
     41     free(const_cast<SharedBuffer*>(released));
     42     return 0;
     43 }
     44 
     45 SharedBuffer* SharedBuffer::edit() const
     46 {
     47     if (onlyOwner()) {
     48         return const_cast<SharedBuffer*>(this);
     49     }
     50     SharedBuffer* sb = alloc(mSize);
     51     if (sb) {
     52         memcpy(sb->data(), data(), size());
     53         release();
     54     }
     55     return sb;
     56 }
     57 
     58 SharedBuffer* SharedBuffer::editResize(size_t newSize) const
     59 {
     60     if (onlyOwner()) {
     61         SharedBuffer* buf = const_cast<SharedBuffer*>(this);
     62         if (buf->mSize == newSize) return buf;
     63         buf = (SharedBuffer*)realloc(buf, sizeof(SharedBuffer) + newSize);
     64         if (buf != NULL) {
     65             buf->mSize = newSize;
     66             return buf;
     67         }
     68     }
     69     SharedBuffer* sb = alloc(newSize);
     70     if (sb) {
     71         const size_t mySize = mSize;
     72         memcpy(sb->data(), data(), newSize < mySize ? newSize : mySize);
     73         release();
     74     }
     75     return sb;
     76 }
     77 
     78 SharedBuffer* SharedBuffer::attemptEdit() const
     79 {
     80     if (onlyOwner()) {
     81         return const_cast<SharedBuffer*>(this);
     82     }
     83     return 0;
     84 }
     85 
     86 SharedBuffer* SharedBuffer::reset(size_t new_size) const
     87 {
     88     // cheap-o-reset.
     89     SharedBuffer* sb = alloc(new_size);
     90     if (sb) {
     91         release();
     92     }
     93     return sb;
     94 }
     95 
     96 void SharedBuffer::acquire() const {
     97     android_atomic_inc(&mRefs);
     98 }
     99 
    100 int32_t SharedBuffer::release(uint32_t flags) const
    101 {
    102     int32_t prev = 1;
    103     if (onlyOwner() || ((prev = android_atomic_dec(&mRefs)) == 1)) {
    104         mRefs = 0;
    105         if ((flags & eKeepStorage) == 0) {
    106             free(const_cast<SharedBuffer*>(this));
    107         }
    108     }
    109     return prev;
    110 }
    111 
    112 
    113 }; // namespace android
    114