1 /* 2 * Copyright (C) 2012 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 /* 18 * Encapsulate a condition variable for thread synchronization. 19 */ 20 21 #include "CondVar.h" 22 #include "NfcJniUtil.h" 23 24 #include <errno.h> 25 #include <string.h> 26 27 #include <android-base/stringprintf.h> 28 #include <base/logging.h> 29 30 using android::base::StringPrintf; 31 32 /******************************************************************************* 33 ** 34 ** Function: CondVar 35 ** 36 ** Description: Initialize member variables. 37 ** 38 ** Returns: None. 39 ** 40 *******************************************************************************/ 41 CondVar::CondVar() { 42 pthread_condattr_t attr; 43 pthread_condattr_init(&attr); 44 pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); 45 memset(&mCondition, 0, sizeof(mCondition)); 46 int const res = pthread_cond_init(&mCondition, &attr); 47 if (res) { 48 LOG(ERROR) << StringPrintf("CondVar::CondVar: fail init; error=0x%X", res); 49 } 50 } 51 52 /******************************************************************************* 53 ** 54 ** Function: ~CondVar 55 ** 56 ** Description: Cleanup all resources. 57 ** 58 ** Returns: None. 59 ** 60 *******************************************************************************/ 61 CondVar::~CondVar() { 62 int const res = pthread_cond_destroy(&mCondition); 63 if (res) { 64 LOG(ERROR) << StringPrintf("CondVar::~CondVar: fail destroy; error=0x%X", 65 res); 66 } 67 } 68 69 /******************************************************************************* 70 ** 71 ** Function: wait 72 ** 73 ** Description: Block the caller and wait for a condition. 74 ** 75 ** Returns: None. 76 ** 77 *******************************************************************************/ 78 void CondVar::wait(Mutex& mutex) { 79 int const res = pthread_cond_wait(&mCondition, mutex.nativeHandle()); 80 if (res) { 81 LOG(ERROR) << StringPrintf("CondVar::wait: fail wait; error=0x%X", res); 82 } 83 } 84 85 /******************************************************************************* 86 ** 87 ** Function: wait 88 ** 89 ** Description: Block the caller and wait for a condition. 90 ** millisec: Timeout in milliseconds. 91 ** 92 ** Returns: True if wait is successful; false if timeout occurs. 93 ** 94 *******************************************************************************/ 95 bool CondVar::wait(Mutex& mutex, long millisec) { 96 bool retVal = false; 97 struct timespec absoluteTime; 98 99 if (clock_gettime(CLOCK_MONOTONIC, &absoluteTime) == -1) { 100 LOG(ERROR) << StringPrintf("CondVar::wait: fail get time; errno=0x%X", 101 errno); 102 } else { 103 absoluteTime.tv_sec += millisec / 1000; 104 long ns = absoluteTime.tv_nsec + ((millisec % 1000) * 1000000); 105 if (ns > 1000000000) { 106 absoluteTime.tv_sec++; 107 absoluteTime.tv_nsec = ns - 1000000000; 108 } else 109 absoluteTime.tv_nsec = ns; 110 } 111 112 int waitResult = 113 pthread_cond_timedwait(&mCondition, mutex.nativeHandle(), &absoluteTime); 114 if ((waitResult != 0) && (waitResult != ETIMEDOUT)) 115 LOG(ERROR) << StringPrintf("CondVar::wait: fail timed wait; error=0x%X", 116 waitResult); 117 retVal = (waitResult == 0); // waited successfully 118 return retVal; 119 } 120 121 /******************************************************************************* 122 ** 123 ** Function: notifyOne 124 ** 125 ** Description: Unblock the waiting thread. 126 ** 127 ** Returns: None. 128 ** 129 *******************************************************************************/ 130 void CondVar::notifyOne() { 131 int const res = pthread_cond_signal(&mCondition); 132 if (res) { 133 LOG(ERROR) << StringPrintf("CondVar::notifyOne: fail signal; error=0x%X", 134 res); 135 } 136 } 137