Home | History | Annotate | Download | only in tinyutils
      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