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 <log/log.h>
     21 
     22 #include "SharedBuffer.h"
     23 
     24 // ---------------------------------------------------------------------------
     25 
     26 namespace android {
     27 
     28 SharedBuffer* SharedBuffer::alloc(size_t size)
     29 {
     30     // Don't overflow if the combined size of the buffer / header is larger than
     31     // size_max.
     32     LOG_ALWAYS_FATAL_IF((size >= (SIZE_MAX - sizeof(SharedBuffer))),
     33                         "Invalid buffer size %zu", size);
     34 
     35     SharedBuffer* sb = static_cast<SharedBuffer *>(malloc(sizeof(SharedBuffer) + size));
     36     if (sb) {
     37         // Should be std::atomic_init(&sb->mRefs, 1);
     38         // But that generates a warning with some compilers.
     39         // The following is OK on Android-supported platforms.
     40         sb->mRefs.store(1, std::memory_order_relaxed);
     41         sb->mSize = size;
     42     }
     43     return sb;
     44 }
     45 
     46 
     47 void SharedBuffer::dealloc(const SharedBuffer* released)
     48 {
     49     free(const_cast<SharedBuffer*>(released));
     50 }
     51 
     52 SharedBuffer* SharedBuffer::edit() const
     53 {
     54     if (onlyOwner()) {
     55         return const_cast<SharedBuffer*>(this);
     56     }
     57     SharedBuffer* sb = alloc(mSize);
     58     if (sb) {
     59         memcpy(sb->data(), data(), size());
     60         release();
     61     }
     62     return sb;
     63 }
     64 
     65 SharedBuffer* SharedBuffer::editResize(size_t newSize) const
     66 {
     67     if (onlyOwner()) {
     68         SharedBuffer* buf = const_cast<SharedBuffer*>(this);
     69         if (buf->mSize == newSize) return buf;
     70         // Don't overflow if the combined size of the new buffer / header is larger than
     71         // size_max.
     72         LOG_ALWAYS_FATAL_IF((newSize >= (SIZE_MAX - sizeof(SharedBuffer))),
     73                             "Invalid buffer size %zu", newSize);
     74 
     75         buf = (SharedBuffer*)realloc(buf, sizeof(SharedBuffer) + newSize);
     76         if (buf != NULL) {
     77             buf->mSize = newSize;
     78             return buf;
     79         }
     80     }
     81     SharedBuffer* sb = alloc(newSize);
     82     if (sb) {
     83         const size_t mySize = mSize;
     84         memcpy(sb->data(), data(), newSize < mySize ? newSize : mySize);
     85         release();
     86     }
     87     return sb;
     88 }
     89 
     90 SharedBuffer* SharedBuffer::attemptEdit() const
     91 {
     92     if (onlyOwner()) {
     93         return const_cast<SharedBuffer*>(this);
     94     }
     95     return 0;
     96 }
     97 
     98 SharedBuffer* SharedBuffer::reset(size_t new_size) const
     99 {
    100     // cheap-o-reset.
    101     SharedBuffer* sb = alloc(new_size);
    102     if (sb) {
    103         release();
    104     }
    105     return sb;
    106 }
    107 
    108 void SharedBuffer::acquire() const {
    109     mRefs.fetch_add(1, std::memory_order_relaxed);
    110 }
    111 
    112 int32_t SharedBuffer::release(uint32_t flags) const
    113 {
    114     int32_t prev = 1;
    115     if (onlyOwner() || ((prev = mRefs.fetch_sub(1, std::memory_order_release) == 1)
    116             && (atomic_thread_fence(std::memory_order_acquire), true))) {
    117         mRefs.store(0, std::memory_order_relaxed);
    118         if ((flags & eKeepStorage) == 0) {
    119             free(const_cast<SharedBuffer*>(this));
    120         }
    121     }
    122     return prev;
    123 }
    124 
    125 
    126 }; // namespace android
    127