blob: c241184303d124d2cb99847163910b782402ec7f [file] [log] [blame]
Glenn Kasten538f4982012-11-26 10:40:24 -08001/*
2 * Copyright (C) 2012 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 <new>
18#include <cutils/atomic.h>
Glenn Kasten538f4982012-11-26 10:40:24 -080019#include <media/SingleStateQueue.h>
20
21namespace android {
22
23template<typename T> SingleStateQueue<T>::Mutator::Mutator(Shared *shared)
24 : mSequence(0), mShared((Shared *) shared)
25{
26 // exactly one of Mutator and Observer must initialize, currently it is Observer
27 //shared->init();
28}
29
30template<typename T> int32_t SingleStateQueue<T>::Mutator::push(const T& value)
31{
32 Shared *shared = mShared;
33 int32_t sequence = mSequence;
34 sequence++;
35 android_atomic_acquire_store(sequence, &shared->mSequence);
36 shared->mValue = value;
37 sequence++;
38 android_atomic_release_store(sequence, &shared->mSequence);
39 mSequence = sequence;
40 // consider signalling a futex here, if we know that observer is waiting
41 return sequence;
42}
43
44template<typename T> bool SingleStateQueue<T>::Mutator::ack()
45{
46 return mShared->mAck - mSequence == 0;
47}
48
49template<typename T> bool SingleStateQueue<T>::Mutator::ack(int32_t sequence)
50{
51 // this relies on 2's complement rollover to detect an ancient sequence number
52 return mShared->mAck - sequence >= 0;
53}
54
55template<typename T> SingleStateQueue<T>::Observer::Observer(Shared *shared)
56 : mSequence(0), mSeed(1), mShared((Shared *) shared)
57{
58 // exactly one of Mutator and Observer must initialize, currently it is Observer
59 shared->init();
60}
61
62template<typename T> bool SingleStateQueue<T>::Observer::poll(T& value)
63{
64 Shared *shared = mShared;
65 int32_t before = shared->mSequence;
66 if (before == mSequence) {
67 return false;
68 }
69 for (int tries = 0; ; ) {
70 const int MAX_TRIES = 5;
71 if (before & 1) {
72 if (++tries >= MAX_TRIES) {
73 return false;
74 }
75 before = shared->mSequence;
76 } else {
77 android_memory_barrier();
78 T temp = shared->mValue;
79 int32_t after = android_atomic_release_load(&shared->mSequence);
80 if (after == before) {
81 value = temp;
82 shared->mAck = before;
83 mSequence = before;
84 return true;
85 }
86 if (++tries >= MAX_TRIES) {
87 return false;
88 }
89 before = after;
90 }
91 }
92}
93
94#if 0
95template<typename T> SingleStateQueue<T>::SingleStateQueue(void /*Shared*/ *shared)
96{
97 ((Shared *) shared)->init();
98}
99#endif
100
101} // namespace android
102
103// hack for gcc
104#ifdef SINGLE_STATE_QUEUE_INSTANTIATIONS
105#include SINGLE_STATE_QUEUE_INSTANTIATIONS
106#endif