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