forked from kaldi-asr/kaldi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkaldi-barrier.cc
More file actions
139 lines (103 loc) · 3.5 KB
/
kaldi-barrier.cc
File metadata and controls
139 lines (103 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// thread/kaldi-barrier.cc
// Copyright 2012 Karel Vesely (Brno University of Technology)
// See ../../COPYING for clarification regarding multiple authors
//
// 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
//
// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
// WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
// MERCHANTABLITY OR NON-INFRINGEMENT.
// See the Apache 2 License for the specific language governing permissions and
// limitations under the License.
#include <pthread.h>
#include "base/kaldi-error.h"
#include "thread/kaldi-barrier.h"
namespace kaldi {
Barrier::Barrier(int32 threshold)
: threshold_(threshold), counter_(threshold), cycle_(0) {
if (pthread_mutex_init(&mutex_, NULL) != 0)
KALDI_ERR << "Cannot initialize pthread mutex";
if (pthread_cond_init(&cv_, NULL) != 0) {
pthread_mutex_destroy(&mutex_);
KALDI_ERR << "Cannot initialize pthread condv";
}
}
Barrier::~Barrier() {
if (pthread_mutex_lock(&mutex_) != 0)
KALDI_ERR << "Cannot lock pthread mutex";
if (counter_ != threshold_) {
pthread_mutex_unlock (&mutex_);
KALDI_ERR << "Cannot destroy barrier with waiting thread(s)";
}
if (pthread_mutex_unlock(&mutex_) != 0)
KALDI_ERR << "Cannot unlock pthread mutex";
if (pthread_mutex_destroy(&mutex_) != 0)
KALDI_ERR << "Cannot destroy pthread mutex";
if (pthread_cond_destroy(&cv_) != 0)
KALDI_ERR << "Cannot destroy pthread condv";
}
void Barrier::SetThreshold(int32 thr) {
if (counter_ != threshold_) {
KALDI_ERR << "Cannot set threshold, while some thread(s) are waiting";
}
threshold_ = thr;
counter_ = thr;
}
/**
* Wait for all the threads to reach a barrier.
* A broadcast wakes all the waiting threads when the counter_ reaches 0.
* The last incoming thread returns -1, the others 0.
*/
int32 Barrier::Wait() {
if (threshold_ == 0)
KALDI_ERR << "Cannot wait when ``threshold'' value was not set";
if (pthread_mutex_lock(&mutex_) != 0)
KALDI_ERR << "Cannot lock pthread mutex";
int32 cycle = cycle_; // memorize which cycle we're in
int32 ret;
if (--counter_ == 0) { // this is the last thread
cycle_ = !cycle_;
counter_ = threshold_;
// wake up.
if (pthread_cond_broadcast(&cv_) != 0) {
KALDI_ERR << "Error on pthred_cond_broadcast";
}
/*
* The last incoming thread will return -1, the others 0
*/
ret = -1;
} else { ///<< NOT A LAST THTREAD
/*
* Wait with thread cancellation disabled, barrier waiting
* should not be a cancellation point.
*/
int32 cancel, tmp;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel);
/*
* Wait until the barrier's cycle_ changes, like this we know
* that the last thread arrived and a brodcast was sent.
*/
while (cycle == cycle_) {
// go to sleep
if (pthread_cond_wait(&cv_, &mutex_) != 0) {
KALDI_ERR << "Error on pthread_cond_wait";
}
}
// Restore the thread's cancel state
pthread_setcancelstate(cancel, &tmp);
/*
* Indicate that it is not the last thread
*/
ret = 0;
}
if (pthread_mutex_unlock (&mutex_) != 0) {
KALDI_ERR << "Error unlcoking pthread mutex";
}
return ret;
}
} // namespace kaldi