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 <device/generic/goldfish/radio/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> Ril_queue(void)94Ril_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> dequeue(void)102T* 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> enqueue(T * request)121void 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> checkAndDequeue(MsgId id,int token)137int 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> empty(void)160int Ril_queue<T>::empty(void) { 161 162 if(this->front == NULL) { 163 return 1; 164 } else { 165 return 0; 166 } 167 } 168