Home | History | Annotate | Download | only in libril
      1 /*
      2 * Copyright (C) 2014 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 "pb_decode.h"
     18 #include <pthread.h>
     19 #include <hardware/ril/librilutils/proto/sap-api.pb.h>
     20 #include <utils/Log.h>
     21 
     22 using namespace std;
     23 
     24 /**
     25  * Template queue class to handling requests for a rild socket.
     26  * <p>
     27  * This class performs the following functions :
     28  * <ul>
     29  *     <li>Enqueue.
     30  *     <li>Dequeue.
     31  *     <li>Check and dequeue.
     32  * </ul>
     33  */
     34 
     35 template <typename T>
     36 class Ril_queue {
     37 
     38    /**
     39      * Mutex attribute used in queue mutex initialization.
     40      */
     41     pthread_mutexattr_t attr;
     42 
     43    /**
     44      * Queue mutex variable for synchronized queue access.
     45      */
     46     pthread_mutex_t mutex_instance;
     47 
     48    /**
     49      * Condition to be waited on for dequeuing.
     50      */
     51     pthread_cond_t cond;
     52 
     53    /**
     54      * Front of the queue.
     55      */
     56     T *front;
     57 
     58     public:
     59 
     60        /**
     61          * Remove the first element of the queue.
     62          *
     63          * @return first element of the queue.
     64          */
     65         T* dequeue(void);
     66 
     67        /**
     68          * Add a request to the front of the queue.
     69          *
     70          * @param Request to be added.
     71          */
     72         void enqueue(T* request);
     73 
     74        /**
     75          * Check if the queue is empty.
     76          */
     77         int empty(void);
     78 
     79        /**
     80          * Check and remove an element with a particular message id and token.
     81          *
     82          * @param Request message id.
     83          * @param Request token.
     84          */
     85         int checkAndDequeue( MsgId id, int token);
     86 
     87        /**
     88          * Queue constructor.
     89          */
     90         Ril_queue(void);
     91 };
     92 
     93 template <typename T>
     94 Ril_queue<T>::Ril_queue(void) {
     95     pthread_mutexattr_init(&attr);
     96     pthread_mutex_init(&mutex_instance, &attr);
     97     cond = PTHREAD_COND_INITIALIZER;
     98     front = NULL;
     99 }
    100 
    101 template <typename T>
    102 T* Ril_queue<T>::dequeue(void) {
    103     T* temp = NULL;
    104 
    105     pthread_mutex_lock(&mutex_instance);
    106     while(empty()) {
    107         pthread_cond_wait(&cond, &mutex_instance);
    108     }
    109     temp = this->front;
    110     if(NULL != this->front->p_next) {
    111         this->front = this->front->p_next;
    112     } else {
    113         this->front = NULL;
    114     }
    115     pthread_mutex_unlock(&mutex_instance);
    116 
    117     return temp;
    118 }
    119 
    120 template <typename T>
    121 void Ril_queue<T>::enqueue(T* request) {
    122 
    123     pthread_mutex_lock(&mutex_instance);
    124 
    125     if(NULL == this->front) {
    126         this->front = request;
    127         request->p_next = NULL;
    128     } else {
    129         request->p_next = this->front;
    130         this->front = request;
    131     }
    132     pthread_cond_broadcast(&cond);
    133     pthread_mutex_unlock(&mutex_instance);
    134 }
    135 
    136 template <typename T>
    137 int Ril_queue<T>::checkAndDequeue(MsgId id, int token) {
    138     int ret = 0;
    139     T* temp;
    140 
    141     pthread_mutex_lock(&mutex_instance);
    142 
    143     for(T **ppCur = &(this->front); *ppCur != NULL; ppCur = &((*ppCur)->p_next)) {
    144         if (token == (*ppCur)->token && id == (*ppCur)->curr->id) {
    145             ret = 1;
    146             temp = *ppCur;
    147             *ppCur = (*ppCur)->p_next;
    148             free(temp);
    149             break;
    150         }
    151     }
    152 
    153     pthread_mutex_unlock(&mutex_instance);
    154 
    155     return ret;
    156 }
    157 
    158 
    159 template <typename T>
    160 int Ril_queue<T>::empty(void) {
    161 
    162     if(this->front == NULL) {
    163         return 1;
    164     } else {
    165         return 0;
    166     }
    167 }
    168