• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 #ifndef OBOETESTER_INFINITE_RECORDING_H
18 #define OBOETESTER_INFINITE_RECORDING_H
19 
20 #include <memory>
21 #include <unistd.h>
22 
23 /**
24  * Record forever. Keep last data.
25  */
26 template <typename T>
27 class InfiniteRecording {
28 public:
InfiniteRecording(size_t maxSamples)29     InfiniteRecording(size_t maxSamples)
30             : mMaxSamples(maxSamples) {
31         mData = std::make_unique<T[]>(mMaxSamples);
32     }
33 
readFrom(T * buffer,size_t position,size_t count)34     int32_t readFrom(T *buffer, size_t position, size_t count) {
35         const size_t maxPosition = mWritten.load();
36         position = std::min(position, maxPosition);
37         size_t numToRead = std::min(count, mMaxSamples);
38         numToRead = std::min(numToRead, maxPosition - position);
39         if (numToRead == 0) return 0;
40         // We may need to read in two parts if it wraps.
41         const size_t offset = position % mMaxSamples;
42         const size_t firstReadSize = std::min(numToRead, mMaxSamples - offset); // till end
43         std::copy(&mData[offset], &mData[offset + firstReadSize], buffer);
44         if (firstReadSize < numToRead) {
45             // Second read needed.
46             std::copy(&mData[0], &mData[numToRead - firstReadSize], &buffer[firstReadSize]);
47         }
48         return numToRead;
49     }
50 
write(T sample)51     void write(T sample) {
52         const size_t position = mWritten.load();
53         const size_t offset = position % mMaxSamples;
54         mData[offset] = sample;
55         mWritten++;
56     }
57 
getTotalWritten()58     int64_t getTotalWritten() {
59         return mWritten.load();
60     }
61 
62 private:
63     std::unique_ptr<T[]> mData;
64     std::atomic<size_t>      mWritten{0};
65     const size_t             mMaxSamples;
66 };
67 #endif //OBOETESTER_INFINITE_RECORDING_H
68