diff options
author | Andy Hung <hunga@google.com> | 2014-12-12 15:35:41 -0800 |
---|---|---|
committer | Andy Hung <hunga@google.com> | 2014-12-19 10:24:55 -0800 |
commit | 9b82924cbd203f1678c2f78aa73b15909efa3e81 (patch) | |
tree | 977b62e2a5d909c8806808614ff5117f75359130 /include/media/SingleStateQueue.h | |
parent | 2590fc421ccf5e8199d511ff3022b428ee9122e9 (diff) | |
download | frameworks_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.h | 78 |
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; |