1 /*
2  * Copyright (C) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "synchronize_event.h"
16 #include <cerrno>
17 #include <cstring>
18 #include "loghelper.h"
19 
20 namespace OHOS {
21 namespace NFC {
22 static const int MILLISECOND_PER_SECOND = 1000;
23 static const int NANOSECOND_PER_MILLISECOND = 1000000;
24 static const int NANOSECOND_PER_SECOND = 1000000000;
25 
SynchronizeEvent()26 SynchronizeEvent::SynchronizeEvent()
27 {
28     pthread_mutex_init(&lock_, nullptr);
29     pthread_condattr_t attr;
30     pthread_condattr_init(&attr);
31     pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
32     pthread_cond_init(&cond_, &attr);
33 }
34 
~SynchronizeEvent()35 SynchronizeEvent::~SynchronizeEvent()
36 {
37     pthread_mutex_destroy(&lock_);
38     pthread_cond_destroy(&cond_);
39 }
40 
Start()41 void SynchronizeEvent::Start()
42 {
43     int res = pthread_mutex_lock(&lock_);
44     if (res != 0) {
45         DebugLog("SynchronizeEvent::start: fail lock; error=0x%{public}X", res);
46     }
47 }
48 
End()49 void SynchronizeEvent::End()
50 {
51     int res = pthread_mutex_unlock(&lock_);
52     if (res != 0) {
53         DebugLog("SynchronizeEvent::end: fail unlock; error=0x%{public}X", res);
54     }
55 }
56 
Wait()57 void SynchronizeEvent::Wait()
58 {
59     int const res = pthread_cond_wait(&cond_, &lock_);
60     if (res) {
61         DebugLog("CondVar::wait: fail wait; error=0x%{public}X", res);
62     }
63 }
64 
Wait(long ms)65 bool SynchronizeEvent::Wait(long ms)
66 {
67     bool retVal = false;
68     struct timespec absoluteTime;
69     clock_gettime(CLOCK_MONOTONIC, &absoluteTime);
70 
71     absoluteTime.tv_sec += ms / MILLISECOND_PER_SECOND;
72     long ns = absoluteTime.tv_nsec + ((ms % MILLISECOND_PER_SECOND) * NANOSECOND_PER_MILLISECOND);
73     if (ns > NANOSECOND_PER_SECOND) {
74         absoluteTime.tv_sec++;
75         absoluteTime.tv_nsec = ns - NANOSECOND_PER_SECOND;
76     } else {
77         absoluteTime.tv_nsec = ns;
78     }
79 
80     int waitResult = pthread_cond_timedwait(&cond_, &lock_, &absoluteTime);
81     if ((waitResult != 0) && (waitResult != ETIMEDOUT)) {
82         DebugLog("SynchronizeEvent::wait: fail timed wait; error=0x%{public}X", waitResult);
83     }
84     retVal = (waitResult == 0);  // waited successfully
85     return retVal;
86 }
87 
NotifyOne()88 void SynchronizeEvent::NotifyOne()
89 {
90     int const res = pthread_cond_signal(&cond_);
91     if (res) {
92         DebugLog("SynchronizeEvent::notifyOne: fail signal; error=0x%{public}X", res);
93     }
94 }
95 }  // namespace NFC
96 }  // namespace OHOS
97