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 <cutils/log.h>
25 #include <errno.h>
26
27
28 /*******************************************************************************
29 **
30 ** Function: CondVar
31 **
32 ** Description: Initialize member variables.
33 **
34 ** Returns: None.
35 **
36 *******************************************************************************/
CondVar()37 CondVar::CondVar ()
38 {
39 memset (&mCondition, 0, sizeof(mCondition));
40 int const res = pthread_cond_init (&mCondition, NULL);
41 if (res)
42 {
43 ALOGE ("CondVar::CondVar: fail init; error=0x%X", res);
44 }
45 }
46
47
48 /*******************************************************************************
49 **
50 ** Function: ~CondVar
51 **
52 ** Description: Cleanup all resources.
53 **
54 ** Returns: None.
55 **
56 *******************************************************************************/
~CondVar()57 CondVar::~CondVar ()
58 {
59 int const res = pthread_cond_destroy (&mCondition);
60 if (res)
61 {
62 ALOGE ("CondVar::~CondVar: fail destroy; error=0x%X", res);
63 }
64 }
65
66
67 /*******************************************************************************
68 **
69 ** Function: wait
70 **
71 ** Description: Block the caller and wait for a condition.
72 **
73 ** Returns: None.
74 **
75 *******************************************************************************/
wait(Mutex & mutex)76 void CondVar::wait (Mutex& mutex)
77 {
78 int const res = pthread_cond_wait (&mCondition, mutex.nativeHandle());
79 if (res)
80 {
81 ALOGE ("CondVar::wait: fail wait; error=0x%X", res);
82 }
83 }
84
85
86 /*******************************************************************************
87 **
88 ** Function: wait
89 **
90 ** Description: Block the caller and wait for a condition.
91 ** millisec: Timeout in milliseconds.
92 **
93 ** Returns: True if wait is successful; false if timeout occurs.
94 **
95 *******************************************************************************/
wait(Mutex & mutex,long millisec)96 bool CondVar::wait (Mutex& mutex, long millisec)
97 {
98 bool retVal = false;
99 struct timespec absoluteTime;
100
101 if (clock_gettime (CLOCK_MONOTONIC, &absoluteTime) == -1)
102 {
103 ALOGE ("CondVar::wait: fail get time; errno=0x%X", errno);
104 }
105 else
106 {
107 absoluteTime.tv_sec += millisec / 1000;
108 long ns = absoluteTime.tv_nsec + ((millisec % 1000) * 1000000);
109 if (ns > 1000000000)
110 {
111 absoluteTime.tv_sec++;
112 absoluteTime.tv_nsec = ns - 1000000000;
113 }
114 else
115 absoluteTime.tv_nsec = ns;
116 }
117
118 //pthread_cond_timedwait_monotonic_np() is an Android-specific function
119 //declared in /development/ndk/platforms/android-9/include/pthread.h;
120 //it uses monotonic clock.
121 //the standard pthread_cond_timedwait() uses realtime clock.
122 int waitResult = pthread_cond_timedwait_monotonic_np (&mCondition, mutex.nativeHandle(), &absoluteTime);
123 if ((waitResult != 0) && (waitResult != ETIMEDOUT))
124 ALOGE ("CondVar::wait: fail timed wait; error=0x%X", waitResult);
125 retVal = (waitResult == 0); //waited successfully
126 return retVal;
127 }
128
129
130 /*******************************************************************************
131 **
132 ** Function: notifyOne
133 **
134 ** Description: Unblock the waiting thread.
135 **
136 ** Returns: None.
137 **
138 *******************************************************************************/
notifyOne()139 void CondVar::notifyOne ()
140 {
141 int const res = pthread_cond_signal (&mCondition);
142 if (res)
143 {
144 ALOGE ("CondVar::notifyOne: fail signal; error=0x%X", res);
145 }
146 }
147
148