diff options
author | Iliyan Malchev <malchev@google.com> | 2011-08-08 11:24:41 -0700 |
---|---|---|
committer | Iliyan Malchev <malchev@google.com> | 2011-08-08 11:46:17 -0700 |
commit | a40968e9b9abcdcc042948ea73346b020279d4b7 (patch) | |
tree | 926da5b4447017617fcc255b490eaee5174a4a9a /libtiutils/MessageQueue.cpp | |
parent | 8558b0909d3f42288f488e6fd1341877c639a594 (diff) | |
download | hardware_ti_omap4-a40968e9b9abcdcc042948ea73346b020279d4b7.zip hardware_ti_omap4-a40968e9b9abcdcc042948ea73346b020279d4b7.tar.gz hardware_ti_omap4-a40968e9b9abcdcc042948ea73346b020279d4b7.tar.bz2 |
initial commit
Change-Id: I8f7a7eeece0e516efa486b77e9d97805c0e65d3e
Signed-off-by: Iliyan Malchev <malchev@google.com>
Diffstat (limited to 'libtiutils/MessageQueue.cpp')
-rwxr-xr-x | libtiutils/MessageQueue.cpp | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/libtiutils/MessageQueue.cpp b/libtiutils/MessageQueue.cpp new file mode 100755 index 0000000..1a5942a --- /dev/null +++ b/libtiutils/MessageQueue.cpp @@ -0,0 +1,397 @@ +/* + * 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 <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) + { + close(this->fd_read); + } + + if(this->fd_write) + { + 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; +} + +/** + @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; + } + +}; |