415 lines
8.7 KiB
C++
415 lines
8.7 KiB
C++
/*
|
|
* Copyright (C) Texas Instruments - http://www.ti.com/
|
|
*
|
|
* 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 <errno.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/poll.h>
|
|
#include <unistd.h>
|
|
#include <utils/Errors.h>
|
|
|
|
|
|
|
|
#define LOG_TAG "MessageQueue"
|
|
#include <utils/Log.h>
|
|
|
|
#include "MessageQueue.h"
|
|
|
|
namespace TIUTILS {
|
|
|
|
/**
|
|
@brief Constructor for the message queue class
|
|
|
|
@param none
|
|
@return none
|
|
*/
|
|
MessageQueue::MessageQueue()
|
|
{
|
|
LOG_FUNCTION_NAME;
|
|
|
|
int fds[2] = {-1,-1};
|
|
android::status_t stat;
|
|
|
|
stat = pipe(fds);
|
|
|
|
if ( 0 > stat )
|
|
{
|
|
MSGQ_LOGEB("Error while openning pipe: %s", strerror(stat) );
|
|
this->fd_read = 0;
|
|
this->fd_write = 0;
|
|
mHasMsg = false;
|
|
}
|
|
else
|
|
{
|
|
this->fd_read = fds[0];
|
|
this->fd_write = fds[1];
|
|
|
|
mHasMsg = false;
|
|
}
|
|
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
}
|
|
|
|
/**
|
|
@brief Destructor for the semaphore class
|
|
|
|
@param none
|
|
@return none
|
|
*/
|
|
MessageQueue::~MessageQueue()
|
|
{
|
|
LOG_FUNCTION_NAME;
|
|
|
|
if(this->fd_read >= 0)
|
|
{
|
|
close(this->fd_read);
|
|
}
|
|
|
|
if(this->fd_write >= 0)
|
|
{
|
|
close(this->fd_write);
|
|
}
|
|
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
}
|
|
|
|
/**
|
|
@brief Get a message from the queue
|
|
|
|
@param msg Message structure to hold the message to be retrieved
|
|
@return android::NO_ERROR On success
|
|
@return android::BAD_VALUE if the message pointer is NULL
|
|
@return android::NO_INIT If the file read descriptor is not set
|
|
@return android::UNKNOWN_ERROR if the read operation fromthe file read descriptor fails
|
|
*/
|
|
android::status_t MessageQueue::get(Message* msg)
|
|
{
|
|
LOG_FUNCTION_NAME;
|
|
|
|
if(!msg)
|
|
{
|
|
MSGQ_LOGEA("msg is NULL");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return android::BAD_VALUE;
|
|
}
|
|
|
|
if(!this->fd_read)
|
|
{
|
|
MSGQ_LOGEA("read descriptor not initialized for message queue");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return android::NO_INIT;
|
|
}
|
|
|
|
char* p = (char*) msg;
|
|
size_t read_bytes = 0;
|
|
|
|
while( read_bytes < sizeof(*msg) )
|
|
{
|
|
int err = read(this->fd_read, p, sizeof(*msg) - read_bytes);
|
|
|
|
if( err < 0 )
|
|
{
|
|
MSGQ_LOGEB("read() error: %s", strerror(errno));
|
|
return android::UNKNOWN_ERROR;
|
|
}
|
|
else
|
|
{
|
|
read_bytes += err;
|
|
}
|
|
}
|
|
|
|
MSGQ_LOGDB("MQ.get(%d,%p,%p,%p,%p)", msg->command, msg->arg1,msg->arg2,msg->arg3,msg->arg4);
|
|
|
|
mHasMsg = false;
|
|
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
@brief Get the input file descriptor of the message queue
|
|
|
|
@param none
|
|
@return file read descriptor
|
|
*/
|
|
|
|
int MessageQueue::getInFd()
|
|
{
|
|
return this->fd_read;
|
|
}
|
|
|
|
/**
|
|
@brief Constructor for the message queue class
|
|
|
|
@param fd file read descriptor
|
|
@return none
|
|
*/
|
|
|
|
void MessageQueue::setInFd(int fd)
|
|
{
|
|
LOG_FUNCTION_NAME;
|
|
|
|
if ( -1 != this->fd_read )
|
|
{
|
|
close(this->fd_read);
|
|
}
|
|
|
|
this->fd_read = fd;
|
|
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
}
|
|
|
|
/**
|
|
@brief Queue a message
|
|
|
|
@param msg Message structure to hold the message to be retrieved
|
|
@return android::NO_ERROR On success
|
|
@return android::BAD_VALUE if the message pointer is NULL
|
|
@return android::NO_INIT If the file write descriptor is not set
|
|
@return android::UNKNOWN_ERROR if the write operation fromthe file write descriptor fails
|
|
*/
|
|
|
|
android::status_t MessageQueue::put(Message* msg)
|
|
{
|
|
LOG_FUNCTION_NAME;
|
|
|
|
char* p = (char*) msg;
|
|
size_t bytes = 0;
|
|
|
|
if(!msg)
|
|
{
|
|
MSGQ_LOGEA("msg is NULL");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return android::BAD_VALUE;
|
|
}
|
|
|
|
if(!this->fd_write)
|
|
{
|
|
MSGQ_LOGEA("write descriptor not initialized for message queue");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return android::NO_INIT;
|
|
}
|
|
|
|
|
|
MSGQ_LOGDB("MQ.put(%d,%p,%p,%p,%p)", msg->command, msg->arg1,msg->arg2,msg->arg3,msg->arg4);
|
|
|
|
while( bytes < sizeof(msg) )
|
|
{
|
|
int err = write(this->fd_write, p, sizeof(*msg) - bytes);
|
|
|
|
if( err < 0 )
|
|
{
|
|
MSGQ_LOGEB("write() error: %s", strerror(errno));
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return android::UNKNOWN_ERROR;
|
|
}
|
|
else
|
|
{
|
|
bytes += err;
|
|
}
|
|
}
|
|
|
|
MSGQ_LOGDA("MessageQueue::put EXIT");
|
|
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/**
|
|
@brief Returns if the message queue is empty or not
|
|
|
|
@param none
|
|
@return true If the queue is empty
|
|
@return false If the queue has at least one message
|
|
*/
|
|
bool MessageQueue::isEmpty()
|
|
{
|
|
LOG_FUNCTION_NAME;
|
|
|
|
struct pollfd pfd;
|
|
|
|
pfd.fd = this->fd_read;
|
|
pfd.events = POLLIN;
|
|
pfd.revents = 0;
|
|
|
|
if(!this->fd_read)
|
|
{
|
|
MSGQ_LOGEA("read descriptor not initialized for message queue");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return android::NO_INIT;
|
|
}
|
|
|
|
|
|
if( -1 == poll(&pfd,1,0) )
|
|
{
|
|
MSGQ_LOGEB("poll() error: %s", strerror(errno));
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return false;
|
|
}
|
|
|
|
if(pfd.revents & POLLIN)
|
|
{
|
|
mHasMsg = true;
|
|
}
|
|
else
|
|
{
|
|
mHasMsg = false;
|
|
}
|
|
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return !mHasMsg;
|
|
}
|
|
|
|
void MessageQueue::clear()
|
|
{
|
|
if(!this->fd_read)
|
|
{
|
|
MSGQ_LOGEA("read descriptor not initialized for message queue");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return;
|
|
}
|
|
|
|
Message msg;
|
|
while(!isEmpty())
|
|
{
|
|
get(&msg);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
@brief Force whether the message queue has message or not
|
|
|
|
@param hasMsg Whether the queue has a message or not
|
|
@return none
|
|
*/
|
|
void MessageQueue::setMsg(bool hasMsg)
|
|
{
|
|
mHasMsg = hasMsg;
|
|
}
|
|
|
|
|
|
/**
|
|
@briefWait for message in maximum three different queues with a timeout
|
|
|
|
@param queue1 First queue. At least this should be set to a valid queue pointer
|
|
@param queue2 Second queue. Optional.
|
|
@param queue3 Third queue. Optional.
|
|
@param timeout The timeout value (in micro secs) to wait for a message in any of the queues
|
|
@return android::NO_ERROR On success
|
|
@return android::BAD_VALUE If queue1 is NULL
|
|
@return android::NO_INIT If the file read descriptor of any of the provided queues is not set
|
|
*/
|
|
android::status_t MessageQueue::waitForMsg(MessageQueue *queue1, MessageQueue *queue2, MessageQueue *queue3, int timeout)
|
|
{
|
|
LOG_FUNCTION_NAME;
|
|
|
|
int n =1;
|
|
struct pollfd pfd[3];
|
|
|
|
if(!queue1)
|
|
{
|
|
MSGQ_LOGEA("queue1 pointer is NULL");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return android::BAD_VALUE;
|
|
}
|
|
|
|
pfd[0].fd = queue1->getInFd();
|
|
if(!pfd[0].fd)
|
|
{
|
|
MSGQ_LOGEA("read descriptor not initialized for message queue1");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return android::NO_INIT;
|
|
}
|
|
pfd[0].events = POLLIN;
|
|
pfd[0].revents = 0;
|
|
if(queue2)
|
|
{
|
|
MSGQ_LOGDA("queue2 not-null");
|
|
pfd[1].fd = queue2->getInFd();
|
|
if(!pfd[1].fd)
|
|
{
|
|
MSGQ_LOGEA("read descriptor not initialized for message queue2");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return android::NO_INIT;
|
|
}
|
|
|
|
pfd[1].events = POLLIN;
|
|
pfd[1].revents = 0;
|
|
n++;
|
|
}
|
|
|
|
if(queue3)
|
|
{
|
|
MSGQ_LOGDA("queue3 not-null");
|
|
pfd[2].fd = queue3->getInFd();
|
|
if(!pfd[2].fd)
|
|
{
|
|
MSGQ_LOGEA("read descriptor not initialized for message queue3");
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return android::NO_INIT;
|
|
}
|
|
|
|
pfd[2].events = POLLIN;
|
|
pfd[2].revents = 0;
|
|
n++;
|
|
}
|
|
|
|
|
|
int ret = poll(pfd, n, timeout);
|
|
if(ret==0)
|
|
{
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return ret;
|
|
}
|
|
|
|
if(ret<android::NO_ERROR)
|
|
{
|
|
MSGQ_LOGEB("Message queue returned error %d", ret);
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return ret;
|
|
}
|
|
|
|
if (pfd[0].revents & POLLIN)
|
|
{
|
|
queue1->setMsg(true);
|
|
}
|
|
|
|
if(queue2)
|
|
{
|
|
if (pfd[1].revents & POLLIN)
|
|
{
|
|
queue2->setMsg(true);
|
|
}
|
|
}
|
|
|
|
if(queue3)
|
|
{
|
|
if (pfd[2].revents & POLLIN)
|
|
{
|
|
queue3->setMsg(true);
|
|
}
|
|
}
|
|
|
|
LOG_FUNCTION_NAME_EXIT;
|
|
return ret;
|
|
}
|
|
|
|
};
|