2 * Copyright (C) 2016 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #ifndef ANDROID_AUDIO_FIFO_INDEX_H
18 #define ANDROID_AUDIO_FIFO_INDEX_H
25 * An index that may optionally be placed in shared memory.
26 * Must be Plain Old Data (POD), so no virtual methods are allowed.
27 * If in shared memory, exactly one process must explicitly call the constructor via placement new.
28 * \see #audio_utils_fifo_sync
30 class audio_utils_fifo_index {
33 audio_utils_fifo_index() : mIndex(0) { }
34 ~audio_utils_fifo_index() { }
37 * Load value of index now with memory order 'acquire'.
41 uint32_t loadAcquire();
44 * Store new value into index now with memory order 'release'.
46 * \param value New value to store into index
48 void storeRelease(uint32_t value);
50 // TODO op should be set in the constructor.
52 * Wait for value of index to change from the specified expected value.
54 * \param op Either FUTEX_WAIT or FUTEX_WAIT_PRIVATE.
55 * \param timeout Indicates the maximum time to block while waiting for value to change.
56 * NULL means to block forever.
57 * Time is expressed as relative CLOCK_MONOTONIC.
58 * We use the Linux kernel representation of time for the very lowest levels,
59 * and save other representations for the APIs that are built on top of this.
60 * This permits APIs to choose the int64_t representation if desired, or the
61 * Linux representation without a double conversion.
63 * \return Zero for success, or a negative error code as specified at "man 2 futex".
65 int wait(int op, uint32_t expected, const struct timespec *timeout);
67 // TODO op should be set in the constructor.
69 * Wake up any threads waiting for the value of index to change.
71 * \param op Either FUTEX_WAIT or FUTEX_WAIT_PRIVATE.
72 * \param waiters Maximum number of waiting threads to wake up.
74 * \return Actual number of threads woken up.
76 int wake(int op, int waiters = 1);
78 // specialized use only, prefer loadAcquire in most cases
79 uint32_t loadConsume();
82 // Linux futex is 32 bits regardless of platform.
83 // It would make more sense to declare this as atomic_uint32_t, but there is no such type name.
84 // TODO Support 64-bit index with 32-bit futex in low-order bits.
85 std::atomic_uint_least32_t mIndex; // accessed by both sides using atomic operations
86 static_assert(sizeof(mIndex) == sizeof(uint32_t), "mIndex must be 32 bits");
89 static_assert(sizeof(audio_utils_fifo_index) == sizeof(uint32_t),
90 "audio_utils_fifo_index must be 32 bits");
93 // From a design POV, these next two classes should be related.
94 // Extract a base class (that shares their property of being a reference to a fifo index)
95 // This should be good in the case if there is a need for generic manipulations on these references.
96 // Or can we perhaps define a template and make two specializations of it.
97 // This is in the case when compile-time polymorphism is sufficient.
100 * A reference to an audio_utils_fifo_index with deferred store-release and deferred wake.
102 * TODO Currently the index and futex share the same 32-bit cell.
103 * In the future, the index may optionally be increased to 64-bits,
104 * and the futex will either be the low-order 32 bits of the index,
105 * or an unrelated 32-bit cell used as a set of event flags.
106 * Both of these will require a change to the API.
108 class RefIndexDeferredStoreReleaseDeferredWake
111 RefIndexDeferredStoreReleaseDeferredWake(audio_utils_fifo_index& index);
112 ~RefIndexDeferredStoreReleaseDeferredWake();
114 // Place 'value' into the cache but do not store it to memory yet.
115 void set(uint32_t value);
117 // If there is a new value in the cache, store it now with memory order 'release'.
120 // Place 'value' into the cache and then store it with memory order 'release'.
121 void writethrough(uint32_t value);
123 // op is FUTEX_WAKE or FUTEX_WAKE_PRIVATE
124 // TODO op should be set in the constructor, and should be abstracted.
125 // waiters is number of waiting threads to wake up
126 void wakeDeferred(int op, int waiters = 1);
127 void wakeNowIfNeeded();
128 // TODO op should be set in the constructor.
129 void wakeNow(int op, int waiters = 1);
132 audio_utils_fifo_index& mIndex; // reference to associated index
133 uint32_t mValue; // cached value to be stored
134 bool mWriteback; // whether the cached value needs to be stored
135 int mWaiters; // number of waiters to wake
136 int mWakeOp; // which kind of wake operation to use
140 * A reference to an audio_utils_fifo_index with cached load-acquire, and deferred wait.
142 * TODO Same as RefIndexDeferredStoreReleaseDeferredWake.
144 class RefIndexCachedLoadAcquireDeferredWait
147 RefIndexCachedLoadAcquireDeferredWait(audio_utils_fifo_index& index);
148 ~RefIndexCachedLoadAcquireDeferredWait();
150 // If value is already cached, return the cached value.
151 // Otherwise load now with memory order 'acquire', cache for later, and return the value.
154 // If value is already cached, this is a no-op.
155 // Otherwise load now with memory order 'acquire' and cache the value for later use.
158 // Discard any value in the cache.
163 * Load a fresh value for index, ignoring any previously cached information.
165 uint32_t readthrough();
168 // TODO This is an immediate wait, but we needed deferred wait
170 * Wait for value of index to change from when it was most recently read with get().
171 * To avoid a race condition, the caller must have already read the index with get(),
172 * and then made the decision to call wait() based on that value.
174 * \param op Either FUTEX_WAIT or FUTEX_WAIT_PRIVATE.
175 * \param timeout Indicates the maximum time to block while waiting for value to change.
176 * NULL means to block forever.
177 * Time is expressed as relative CLOCK_MONOTONIC.
178 * See above for explanation of why representation is struct timespec.
180 * \return Zero for success, or a negative error code as specified at "man 2 futex".
181 * \retval -EINVAL caller did not call get() prior to wait()
183 int wait(int op, const struct timespec *timeout);
186 audio_utils_fifo_index& mIndex; // reference to associated index
187 uint32_t mValue; // most recently cached value
188 bool mLoaded; // whether mValue is valid
191 #endif // !ANDROID_AUDIO_FIFO_INDEX_H