| 30 |
ashish |
1 |
/*
|
|
|
2 |
* Licensed to the Apache Software Foundation (ASF) under one
|
|
|
3 |
* or more contributor license agreements. See the NOTICE file
|
|
|
4 |
* distributed with this work for additional information
|
|
|
5 |
* regarding copyright ownership. The ASF licenses this file
|
|
|
6 |
* to you under the Apache License, Version 2.0 (the
|
|
|
7 |
* "License"); you may not use this file except in compliance
|
|
|
8 |
* with the License. You may obtain a copy of the License at
|
|
|
9 |
*
|
|
|
10 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
11 |
*
|
|
|
12 |
* Unless required by applicable law or agreed to in writing,
|
|
|
13 |
* software distributed under the License is distributed on an
|
|
|
14 |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
|
15 |
* KIND, either express or implied. See the License for the
|
|
|
16 |
* specific language governing permissions and limitations
|
|
|
17 |
* under the License.
|
|
|
18 |
*/
|
|
|
19 |
|
|
|
20 |
#include "Monitor.h"
|
|
|
21 |
#include "Exception.h"
|
|
|
22 |
#include "Util.h"
|
|
|
23 |
|
|
|
24 |
#include <assert.h>
|
|
|
25 |
#include <errno.h>
|
|
|
26 |
|
|
|
27 |
#include <iostream>
|
|
|
28 |
|
|
|
29 |
#include <pthread.h>
|
|
|
30 |
|
|
|
31 |
namespace apache { namespace thrift { namespace concurrency {
|
|
|
32 |
|
|
|
33 |
/**
|
|
|
34 |
* Monitor implementation using the POSIX pthread library
|
|
|
35 |
*
|
|
|
36 |
* @version $Id:$
|
|
|
37 |
*/
|
|
|
38 |
class Monitor::Impl {
|
|
|
39 |
|
|
|
40 |
public:
|
|
|
41 |
|
|
|
42 |
Impl() :
|
|
|
43 |
mutexInitialized_(false),
|
|
|
44 |
condInitialized_(false) {
|
|
|
45 |
|
|
|
46 |
if (pthread_mutex_init(&pthread_mutex_, NULL) == 0) {
|
|
|
47 |
mutexInitialized_ = true;
|
|
|
48 |
|
|
|
49 |
if (pthread_cond_init(&pthread_cond_, NULL) == 0) {
|
|
|
50 |
condInitialized_ = true;
|
|
|
51 |
}
|
|
|
52 |
}
|
|
|
53 |
|
|
|
54 |
if (!mutexInitialized_ || !condInitialized_) {
|
|
|
55 |
cleanup();
|
|
|
56 |
throw SystemResourceException();
|
|
|
57 |
}
|
|
|
58 |
}
|
|
|
59 |
|
|
|
60 |
~Impl() { cleanup(); }
|
|
|
61 |
|
|
|
62 |
void lock() const { pthread_mutex_lock(&pthread_mutex_); }
|
|
|
63 |
|
|
|
64 |
void unlock() const { pthread_mutex_unlock(&pthread_mutex_); }
|
|
|
65 |
|
|
|
66 |
void wait(int64_t timeout) const {
|
|
|
67 |
|
|
|
68 |
// XXX Need to assert that caller owns mutex
|
|
|
69 |
assert(timeout >= 0LL);
|
|
|
70 |
if (timeout == 0LL) {
|
|
|
71 |
int iret = pthread_cond_wait(&pthread_cond_, &pthread_mutex_);
|
|
|
72 |
assert(iret == 0);
|
|
|
73 |
} else {
|
|
|
74 |
struct timespec abstime;
|
|
|
75 |
int64_t now = Util::currentTime();
|
|
|
76 |
Util::toTimespec(abstime, now + timeout);
|
|
|
77 |
int result = pthread_cond_timedwait(&pthread_cond_,
|
|
|
78 |
&pthread_mutex_,
|
|
|
79 |
&abstime);
|
|
|
80 |
if (result == ETIMEDOUT) {
|
|
|
81 |
// pthread_cond_timedwait has been observed to return early on
|
|
|
82 |
// various platforms, so comment out this assert.
|
|
|
83 |
//assert(Util::currentTime() >= (now + timeout));
|
|
|
84 |
throw TimedOutException();
|
|
|
85 |
}
|
|
|
86 |
}
|
|
|
87 |
}
|
|
|
88 |
|
|
|
89 |
void notify() {
|
|
|
90 |
// XXX Need to assert that caller owns mutex
|
|
|
91 |
int iret = pthread_cond_signal(&pthread_cond_);
|
|
|
92 |
assert(iret == 0);
|
|
|
93 |
}
|
|
|
94 |
|
|
|
95 |
void notifyAll() {
|
|
|
96 |
// XXX Need to assert that caller owns mutex
|
|
|
97 |
int iret = pthread_cond_broadcast(&pthread_cond_);
|
|
|
98 |
assert(iret == 0);
|
|
|
99 |
}
|
|
|
100 |
|
|
|
101 |
private:
|
|
|
102 |
|
|
|
103 |
void cleanup() {
|
|
|
104 |
if (mutexInitialized_) {
|
|
|
105 |
mutexInitialized_ = false;
|
|
|
106 |
int iret = pthread_mutex_destroy(&pthread_mutex_);
|
|
|
107 |
assert(iret == 0);
|
|
|
108 |
}
|
|
|
109 |
|
|
|
110 |
if (condInitialized_) {
|
|
|
111 |
condInitialized_ = false;
|
|
|
112 |
int iret = pthread_cond_destroy(&pthread_cond_);
|
|
|
113 |
assert(iret == 0);
|
|
|
114 |
}
|
|
|
115 |
}
|
|
|
116 |
|
|
|
117 |
mutable pthread_mutex_t pthread_mutex_;
|
|
|
118 |
mutable bool mutexInitialized_;
|
|
|
119 |
mutable pthread_cond_t pthread_cond_;
|
|
|
120 |
mutable bool condInitialized_;
|
|
|
121 |
};
|
|
|
122 |
|
|
|
123 |
Monitor::Monitor() : impl_(new Monitor::Impl()) {}
|
|
|
124 |
|
|
|
125 |
Monitor::~Monitor() { delete impl_; }
|
|
|
126 |
|
|
|
127 |
void Monitor::lock() const { impl_->lock(); }
|
|
|
128 |
|
|
|
129 |
void Monitor::unlock() const { impl_->unlock(); }
|
|
|
130 |
|
|
|
131 |
void Monitor::wait(int64_t timeout) const { impl_->wait(timeout); }
|
|
|
132 |
|
|
|
133 |
void Monitor::notify() const { impl_->notify(); }
|
|
|
134 |
|
|
|
135 |
void Monitor::notifyAll() const { impl_->notifyAll(); }
|
|
|
136 |
|
|
|
137 |
}}} // apache::thrift::concurrency
|