blob: ef453fa6c38410a080ddb0d70165c417c655acf0 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
Mathias Agopian9857d992013-04-01 15:17:55 -07002 * Copyright 2005 The Android Open Source Project
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08003 *
Mathias Agopian9857d992013-04-01 15:17:55 -07004 * 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
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08007 *
Mathias Agopian9857d992013-04-01 15:17:55 -07008 * 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.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080015 */
16
17#include <stdlib.h>
18#include <string.h>
19
20#include <cutils/atomic.h>
21
Mathias Agopian9857d992013-04-01 15:17:55 -070022#include "SharedBuffer.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080023
24// ---------------------------------------------------------------------------
25
26namespace android {
Mathias Agopian9857d992013-04-01 15:17:55 -070027namespace tinyutils {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080028
29SharedBuffer* 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
40ssize_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
47SharedBuffer* 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
60SharedBuffer* 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
80SharedBuffer* SharedBuffer::attemptEdit() const
81{
82 if (onlyOwner()) {
83 return const_cast<SharedBuffer*>(this);
84 }
85 return 0;
86}
87
88SharedBuffer* 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
98void SharedBuffer::acquire() const {
99 android_atomic_inc(&mRefs);
100}
101
102int32_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
Mathias Agopian9857d992013-04-01 15:17:55 -0700114} // namespace tinyutils
115} // namespace android