| /* |
| * 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 "Semaphore.h" |
| #include "ErrorUtils.h" |
| #include <utils/Log.h> |
| #include <time.h> |
| |
| namespace android { |
| |
| /** |
| @brief Constructor for the semaphore class |
| |
| @param none |
| @return none |
| */ |
| Semaphore::Semaphore() |
| { |
| ///Initialize the semaphore to NULL |
| mSemaphore = NULL; |
| } |
| |
| /** |
| @brief Destructor of the semaphore class |
| |
| @param none |
| @return none |
| |
| */ |
| Semaphore::~Semaphore() |
| { |
| Release(); |
| } |
| |
| /** |
| @brief: Releases semaphore |
| |
| @param count >=0 |
| @return NO_ERROR On Success |
| @return One of the android error codes based on semaphore de-initialization |
| */ |
| |
| status_t Semaphore::Release() |
| { |
| int status = 0; |
| |
| ///Destroy only if the semaphore has been created |
| if(mSemaphore) |
| { |
| status = sem_destroy(mSemaphore); |
| |
| free(mSemaphore); |
| |
| mSemaphore = NULL; |
| } |
| |
| ///Initialize the semaphore and return the status |
| return ErrorUtils::posixToAndroidError(status); |
| |
| } |
| |
| /** |
| @brief Create the semaphore with initial count value |
| |
| @param count >=0 |
| @return NO_ERROR On Success |
| @return NO_MEMORY If unable to allocate memory for the semaphore |
| @return BAD_VALUE If an invalid count value is passed (<0) |
| @return One of the android error codes based on semaphore initialization |
| */ |
| |
| status_t Semaphore::Create(int count) |
| { |
| status_t ret = NO_ERROR; |
| |
| ///count cannot be less than zero |
| if(count<0) |
| { |
| return BAD_VALUE; |
| } |
| |
| ret = Release(); |
| if ( NO_ERROR != ret ) |
| { |
| return ret; |
| } |
| |
| ///allocate memory for the semaphore |
| mSemaphore = (sem_t*)malloc(sizeof(sem_t)) ; |
| |
| ///if memory is unavailable, return error |
| if(!mSemaphore) |
| { |
| return NO_MEMORY; |
| } |
| |
| ///Initialize the semaphore and return the status |
| return ErrorUtils::posixToAndroidError(sem_init(mSemaphore, 0x00, count)); |
| |
| } |
| |
| /** |
| @brief Wait operation |
| |
| @param none |
| @return BAD_VALUE if the semaphore is not initialized |
| @return NO_ERROR On success |
| @return One of the android error codes based on semaphore wait operation |
| */ |
| status_t Semaphore::Wait() |
| { |
| ///semaphore should have been created first |
| if(!mSemaphore) |
| { |
| return BAD_VALUE; |
| } |
| |
| ///Wait and return the status after signalling |
| return ErrorUtils::posixToAndroidError(sem_wait(mSemaphore)); |
| |
| |
| } |
| |
| |
| /** |
| @brief Signal operation |
| |
| @param none |
| @return BAD_VALUE if the semaphore is not initialized |
| @return NO_ERROR On success |
| @return One of the android error codes based on semaphore signal operation |
| */ |
| |
| status_t Semaphore::Signal() |
| { |
| ///semaphore should have been created first |
| if(!mSemaphore) |
| { |
| return BAD_VALUE; |
| } |
| |
| ///Post to the semaphore |
| return ErrorUtils::posixToAndroidError(sem_post(mSemaphore)); |
| |
| } |
| |
| /** |
| @brief Current semaphore count |
| |
| @param none |
| @return Current count value of the semaphore |
| */ |
| int Semaphore::Count() |
| { |
| int val; |
| |
| ///semaphore should have been created first |
| if(!mSemaphore) |
| { |
| return BAD_VALUE; |
| } |
| |
| ///get the value of the semaphore |
| sem_getvalue(mSemaphore, &val); |
| |
| return val; |
| } |
| |
| /** |
| @brief Wait operation with a timeout |
| |
| @param timeoutMicroSecs The timeout period in micro seconds |
| @return BAD_VALUE if the semaphore is not initialized |
| @return NO_ERROR On success |
| @return One of the android error codes based on semaphore wait operation |
| */ |
| |
| status_t Semaphore::WaitTimeout(int timeoutMicroSecs) |
| { |
| status_t ret = NO_ERROR; |
| |
| struct timespec timeSpec; |
| struct timeval currentTime; |
| |
| ///semaphore should have been created first |
| if( NULL == mSemaphore) |
| { |
| ret = BAD_VALUE; |
| } |
| |
| if ( NO_ERROR == ret ) |
| { |
| |
| ///setup the timeout values - timeout is specified in seconds and nanoseconds |
| gettimeofday(¤tTime, NULL); |
| timeSpec.tv_sec = currentTime.tv_sec; |
| timeSpec.tv_nsec = currentTime.tv_usec * 1000; |
| timeSpec.tv_sec += ( timeoutMicroSecs / 1000000 ); |
| timeSpec.tv_nsec += ( timeoutMicroSecs % 1000000) * 1000; |
| |
| ///Wait for the timeout or signal and return the result based on whichever event occurred first |
| ret = sem_timedwait(mSemaphore, &timeSpec); |
| } |
| |
| if ( NO_ERROR != ret ) |
| { |
| Signal(); |
| Create(0); |
| } |
| |
| return ret; |
| } |
| |
| |
| }; |
| |
| |