1 /*
2  * Copyright (C) 2015 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 //#define LOG_DEBUG     1
18 #define LOG_TAG "ring"
19 #include <utils/Log.h>
20 
21 #include "ring.h"
22 
23 #include <stdlib.h>
24 #include <string.h>
25 
26 namespace android {
27 
RingBuffer(size_t size)28 RingBuffer::RingBuffer(size_t size)
29     : mSize(size),
30       mData((sensors_event_t *)malloc(sizeof(sensors_event_t) * mSize)),
31       mReadPos(0),
32       mWritePos(0) {
33 }
34 
~RingBuffer()35 RingBuffer::~RingBuffer() {
36     free(mData);
37     mData = NULL;
38 }
39 
write(const sensors_event_t * ev,size_t size)40 ssize_t RingBuffer::write(const sensors_event_t *ev, size_t size) {
41     Mutex::Autolock autoLock(mLock);
42 
43     size_t numAvailableToRead = mWritePos - mReadPos;
44     size_t numAvailableToWrite = mSize - numAvailableToRead;
45 
46     if (size > numAvailableToWrite) {
47         size = numAvailableToWrite;
48     }
49 
50     size_t writePos = (mWritePos % mSize);
51     size_t copy = mSize - writePos;
52 
53     if (copy > size) {
54         copy = size;
55     }
56 
57     memcpy(&mData[writePos], ev, copy * sizeof(sensors_event_t));
58 
59     if (size > copy) {
60         memcpy(mData, &ev[copy], (size - copy) * sizeof(sensors_event_t));
61     }
62 
63     mWritePos += size;
64 
65     if (numAvailableToRead == 0 && size > 0) {
66         mNotEmptyCondition.broadcast();
67     }
68 
69     return size;
70 }
71 
read(sensors_event_t * ev,size_t size)72 ssize_t RingBuffer::read(sensors_event_t *ev, size_t size) {
73     Mutex::Autolock autoLock(mLock);
74 
75     size_t numAvailableToRead;
76     for (;;) {
77         numAvailableToRead = mWritePos - mReadPos;
78         if (numAvailableToRead > 0) {
79             break;
80         }
81 
82         mNotEmptyCondition.wait(mLock);
83     }
84 
85     if (size > numAvailableToRead) {
86         size = numAvailableToRead;
87     }
88 
89     size_t readPos = (mReadPos % mSize);
90     size_t copy = mSize - readPos;
91 
92     if (copy > size) {
93         copy = size;
94     }
95 
96     memcpy(ev, &mData[readPos], copy * sizeof(sensors_event_t));
97 
98     if (size > copy) {
99         memcpy(&ev[copy], mData, (size - copy) * sizeof(sensors_event_t));
100     }
101 
102     mReadPos += size;
103 
104     return size;
105 }
106 
107 }  // namespace android
108 
109