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 #ifndef ANDROID_AUDIO_FIFO_WRITER32_H
18 #define ANDROID_AUDIO_FIFO_WRITER32_H
19 
20 #include <audio_utils/fifo.h>
21 
22 /**
23  * Optimized FIFO writer for small multiples of fixed-sized POD such as primitives.
24  *
25  * Has these restrictions compared to the ordinary FIFO writer:
26  *  - buffer must be aligned on an appropriate boundary for T
27  *  - frame size must be sizeof(T)
28  *  - capacity must be power-of-2
29  *  - effective size must be equal to capacity
30  *  - no support for throttling of writer by one reader, and thus no blocking writes
31  *  - does not implement the provider interface
32  *  - does not implement the ordinary writer interface
33  *  - does not unblock a reader
34  *  - return value from write methods is void
35  *  - no implied store-release; must be done explicitly
36  *  - may not be combined with ordinary writer
37  *
38  * Usage:
39  *  - construct an ordinary FIFO that follows the restrictions above
40  *  - construct an ordinary reader based on that FIFO
41  *  - construct a writer_T using the FIFO
42  *  - use a sequence of write and write1, followed by storeSingleThreaded or storeRelease to commit
43  */
44 template <typename T>
45 class audio_utils_fifo_writer_T /* : public audio_utils_fifo_provider */ {
46 
47 public:
48     /**
49      * Construct a writer_T from a FIFO.
50      */
51     explicit audio_utils_fifo_writer_T(audio_utils_fifo& fifo);
52     /*virtual*/ ~audio_utils_fifo_writer_T();
53 
54     /**
55      * Write an array of T to FIFO.
56      * If count is larger than capacity, then only the initial 'capacity' frames will be written.
57      * TODO Instead of a silent truncation, consider adding a size_t or ssize_t return value
58      * to indicate the actual transfer count.
59      */
60     void write(const T *buffer, uint32_t count /* FIXME size_t in writer */);
61 
62     /**
63      * Write one T value to FIFO.
64      */
write1(const T & value)65     void write1(const T& value)
66             __attribute__((no_sanitize("integer")))     // mLocalRear ++ can wrap
67     {
68         mBuffer[mLocalRear++ & (mFrameCountP2 - 1)] = value;
69     }
70 
71     /**
72      * Commit all previous write and write1 so that they are observable by reader(s),
73      * with a simple non-atomic memory write.
74      */
storeSingleThreaded()75     void storeSingleThreaded() {
76         mWriterRear.storeSingleThreaded(mLocalRear);
77     }
78 
79     /**
80      * Commit all previous write and write1 so that they are observable by reader(s),
81      * with memory order 'release'.
82      */
storeRelease()83     void storeRelease() {
84         mWriterRear.storeRelease(mLocalRear);
85     }
86 
87 private:
88     // Accessed by writer only using ordinary operations
89     uint32_t    mLocalRear; // frame index of next frame slot available to write, or write index
90 
91     // These fields are copied from fifo for better performance (avoids an extra de-reference)
92     const uint32_t          mFrameCountP2;
93     T * const               mBuffer;
94     audio_utils_fifo_index& mWriterRear;
95 };
96 
97 using audio_utils_fifo_writer32 = audio_utils_fifo_writer_T<int32_t>;
98 using audio_utils_fifo_writer64 = audio_utils_fifo_writer_T<int64_t>;
99 
100 #endif // ANDROID_AUDIO_FIFO_WRITER32_H
101