/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "pb_decode.h"
#include <pthread.h>
#include <hardware/ril/librilutils/proto/sap-api.pb.h>
#include <utils/Log.h>
using namespace std;
/**
* Template queue class to handling requests for a rild socket.
* <p>
* This class performs the following functions :
* <ul>
* <li>Enqueue.
* <li>Dequeue.
* <li>Check and dequeue.
* </ul>
*/
template <typename T>
class Ril_queue {
/**
* Mutex attribute used in queue mutex initialization.
*/
pthread_mutexattr_t attr;
/**
* Queue mutex variable for synchronized queue access.
*/
pthread_mutex_t mutex_instance;
/**
* Condition to be waited on for dequeuing.
*/
pthread_cond_t cond;
/**
* Front of the queue.
*/
T *front;
public:
/**
* Remove the first element of the queue.
*
* @return first element of the queue.
*/
T* dequeue(void);
/**
* Add a request to the front of the queue.
*
* @param Request to be added.
*/
void enqueue(T* request);
/**
* Check if the queue is empty.
*/
int empty(void);
/**
* Check and remove an element with a particular message id and token.
*
* @param Request message id.
* @param Request token.
*/
int checkAndDequeue( MsgId id, int token);
/**
* Queue constructor.
*/
Ril_queue(void);
};
template <typename T>
Ril_queue<T>::Ril_queue(void) {
pthread_mutexattr_init(&attr);
pthread_mutex_init(&mutex_instance, &attr);
cond = PTHREAD_COND_INITIALIZER;
front = NULL;
}
template <typename T>
T* Ril_queue<T>::dequeue(void) {
T* temp = NULL;
pthread_mutex_lock(&mutex_instance);
while(empty()) {
pthread_cond_wait(&cond, &mutex_instance);
}
temp = this->front;
if(NULL != this->front->p_next) {
this->front = this->front->p_next;
} else {
this->front = NULL;
}
pthread_mutex_unlock(&mutex_instance);
return temp;
}
template <typename T>
void Ril_queue<T>::enqueue(T* request) {
pthread_mutex_lock(&mutex_instance);
if(NULL == this->front) {
this->front = request;
request->p_next = NULL;
} else {
request->p_next = this->front;
this->front = request;
}
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex_instance);
}
template <typename T>
int Ril_queue<T>::checkAndDequeue(MsgId id, int token) {
int ret = 0;
T* temp;
pthread_mutex_lock(&mutex_instance);
for(T **ppCur = &(this->front); *ppCur != NULL; ppCur = &((*ppCur)->p_next)) {
if (token == (*ppCur)->token && id == (*ppCur)->curr->id) {
ret = 1;
temp = *ppCur;
*ppCur = (*ppCur)->p_next;
free(temp);
break;
}
}
pthread_mutex_unlock(&mutex_instance);
return ret;
}
template <typename T>
int Ril_queue<T>::empty(void) {
if(this->front == NULL) {
return 1;
} else {
return 0;
}
}