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 <log/log.h>
28 
29 /*******************************************************************************
30 **
31 ** Function:        CondVar
32 **
33 ** Description:     Initialize member variables.
34 **
35 ** Returns:         None.
36 **
37 *******************************************************************************/
CondVar()38 CondVar::CondVar ()
39 {
40     pthread_condattr_t attr;
41     pthread_condattr_init(&attr);
42     pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
43     memset (&mCondition, 0, sizeof(mCondition));
44     int const res = pthread_cond_init (&mCondition, &attr);
45     if (res)
46     {
47         ALOGE("CondVar::CondVar: fail init; error=0x%X", res);
48     }
49 }
50 
51 
52 /*******************************************************************************
53 **
54 ** Function:        ~CondVar
55 **
56 ** Description:     Cleanup all resources.
57 **
58 ** Returns:         None.
59 **
60 *******************************************************************************/
~CondVar()61 CondVar::~CondVar ()
62 {
63     int const res = pthread_cond_destroy (&mCondition);
64     if (res)
65     {
66         ALOGE("CondVar::~CondVar: fail destroy; error=0x%X", res);
67     }
68 }
69 
70 
71 /*******************************************************************************
72 **
73 ** Function:        wait
74 **
75 ** Description:     Block the caller and wait for a condition.
76 **
77 ** Returns:         None.
78 **
79 *******************************************************************************/
wait(Mutex & mutex)80 void CondVar::wait (Mutex& mutex)
81 {
82     int const res = pthread_cond_wait (&mCondition, mutex.nativeHandle());
83     if (res)
84     {
85         ALOGE("CondVar::wait: fail wait; error=0x%X", res);
86     }
87 }
88 
89 
90 /*******************************************************************************
91 **
92 ** Function:        wait
93 **
94 ** Description:     Block the caller and wait for a condition.
95 **                  millisec: Timeout in milliseconds.
96 **
97 ** Returns:         True if wait is successful; false if timeout occurs.
98 **
99 *******************************************************************************/
wait(Mutex & mutex,long millisec)100 bool CondVar::wait (Mutex& mutex, long millisec)
101 {
102     bool retVal = false;
103     struct timespec absoluteTime;
104 
105     if (clock_gettime (CLOCK_MONOTONIC, &absoluteTime) == -1)
106     {
107         ALOGE("CondVar::wait: fail get time; errno=0x%X", errno);
108     }
109     else
110     {
111         absoluteTime.tv_sec += millisec / 1000;
112         long ns = absoluteTime.tv_nsec + ((millisec % 1000) * 1000000);
113         if (ns > 1000000000)
114         {
115             absoluteTime.tv_sec++;
116             absoluteTime.tv_nsec = ns - 1000000000;
117         }
118         else
119             absoluteTime.tv_nsec = ns;
120     }
121 
122     int waitResult = pthread_cond_timedwait (&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