summaryrefslogtreecommitdiffstats
path: root/include/media/SingleStateQueue.h
diff options
context:
space:
mode:
authorAndy Hung <hunga@google.com>2014-12-12 15:35:41 -0800
committerAndy Hung <hunga@google.com>2014-12-19 10:24:55 -0800
commit9b82924cbd203f1678c2f78aa73b15909efa3e81 (patch)
tree977b62e2a5d909c8806808614ff5117f75359130 /include/media/SingleStateQueue.h
parent2590fc421ccf5e8199d511ff3022b428ee9122e9 (diff)
downloadframeworks_av-9b82924cbd203f1678c2f78aa73b15909efa3e81.zip
frameworks_av-9b82924cbd203f1678c2f78aa73b15909efa3e81.tar.gz
frameworks_av-9b82924cbd203f1678c2f78aa73b15909efa3e81.tar.bz2
Remove explicit instantiation of SingleStateQueue
Refactoring now possible due to changes in the Android atomic include. Change-Id: Ia0094d322d9ad3d8c186307306821376ca8002c4
Diffstat (limited to 'include/media/SingleStateQueue.h')
-rw-r--r--include/media/SingleStateQueue.h78
1 files changed, 66 insertions, 12 deletions
diff --git a/include/media/SingleStateQueue.h b/include/media/SingleStateQueue.h
index 04c5fd0..e2e58c5 100644
--- a/include/media/SingleStateQueue.h
+++ b/include/media/SingleStateQueue.h
@@ -21,6 +21,7 @@
// Non-blocking single-reader / single-writer multi-word atomic load / store
#include <stdint.h>
+#include <cutils/atomic.h>
namespace android {
@@ -41,28 +42,47 @@ private:
void init() { mAck = 0; mSequence = 0; }
volatile int32_t mAck;
-#if 0
- int mPad[7];
- // cache line boundary
-#endif
volatile int32_t mSequence;
T mValue;
};
class Mutator {
public:
- Mutator(Shared *shared);
- /*virtual*/ ~Mutator() { }
+ Mutator(Shared *shared)
+ : mSequence(0), mShared(shared)
+ {
+ // exactly one of Mutator and Observer must initialize, currently it is Observer
+ // shared->init();
+ }
// push new value onto state queue, overwriting previous value;
// returns a sequence number which can be used with ack()
- int32_t push(const T& value);
+ int32_t push(const T& value)
+ {
+ Shared *shared = mShared;
+ int32_t sequence = mSequence;
+ sequence++;
+ android_atomic_acquire_store(sequence, &shared->mSequence);
+ shared->mValue = value;
+ sequence++;
+ android_atomic_release_store(sequence, &shared->mSequence);
+ mSequence = sequence;
+ // consider signalling a futex here, if we know that observer is waiting
+ return sequence;
+ }
// return true if most recent push has been observed
- bool ack();
+ bool ack() const
+ {
+ return mShared->mAck - mSequence == 0;
+ }
// return true if a push with specified sequence number or later has been observed
- bool ack(int32_t sequence);
+ bool ack(int32_t sequence) const
+ {
+ // this relies on 2's complement rollover to detect an ancient sequence number
+ return mShared->mAck - sequence >= 0;
+ }
private:
int32_t mSequence;
@@ -71,11 +91,45 @@ private:
class Observer {
public:
- Observer(Shared *shared);
- /*virtual*/ ~Observer() { }
+ Observer(Shared *shared)
+ : mSequence(0), mSeed(1), mShared(shared)
+ {
+ // exactly one of Mutator and Observer must initialize, currently it is Observer
+ shared->init();
+ }
// return true if value has changed
- bool poll(T& value);
+ bool poll(T& value)
+ {
+ Shared *shared = mShared;
+ int32_t before = shared->mSequence;
+ if (before == mSequence) {
+ return false;
+ }
+ for (int tries = 0; ; ) {
+ const int MAX_TRIES = 5;
+ if (before & 1) {
+ if (++tries >= MAX_TRIES) {
+ return false;
+ }
+ before = shared->mSequence;
+ } else {
+ android_memory_barrier();
+ T temp = shared->mValue;
+ int32_t after = android_atomic_release_load(&shared->mSequence);
+ if (after == before) {
+ value = temp;
+ shared->mAck = before;
+ mSequence = before;
+ return true;
+ }
+ if (++tries >= MAX_TRIES) {
+ return false;
+ }
+ before = after;
+ }
+ }
+ }
private:
int32_t mSequence;