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