mutex_nonprod.cc
Go to the documentation of this file.
00001 // Copyright 2017 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 // Implementation of a small subset of Mutex and CondVar functionality
00016 // for platforms where the production implementation hasn't been fully
00017 // ported yet.
00018 
00019 #include "absl/synchronization/mutex.h"
00020 
00021 #if defined(_WIN32)
00022 #include <chrono>  // NOLINT(build/c++11)
00023 #else
00024 #include <sys/time.h>
00025 #include <time.h>
00026 #endif
00027 
00028 #include <algorithm>
00029 
00030 #include "absl/base/internal/raw_logging.h"
00031 #include "absl/time/time.h"
00032 
00033 namespace absl {
00034 namespace synchronization_internal {
00035 
00036 namespace {
00037 
00038 // Return the current time plus the timeout.
00039 absl::Time DeadlineFromTimeout(absl::Duration timeout) {
00040   return absl::Now() + timeout;
00041 }
00042 
00043 // Limit the deadline to a positive, 32-bit time_t value to accommodate
00044 // implementation restrictions.  This also deals with InfinitePast and
00045 // InfiniteFuture.
00046 absl::Time LimitedDeadline(absl::Time deadline) {
00047   deadline = std::max(absl::FromTimeT(0), deadline);
00048   deadline = std::min(deadline, absl::FromTimeT(0x7fffffff));
00049   return deadline;
00050 }
00051 
00052 }  // namespace
00053 
00054 #if defined(_WIN32)
00055 
00056 MutexImpl::MutexImpl() {}
00057 
00058 MutexImpl::~MutexImpl() {
00059   if (locked_) {
00060     std_mutex_.unlock();
00061   }
00062 }
00063 
00064 void MutexImpl::Lock() {
00065   std_mutex_.lock();
00066   locked_ = true;
00067 }
00068 
00069 bool MutexImpl::TryLock() {
00070   bool locked = std_mutex_.try_lock();
00071   if (locked) locked_ = true;
00072   return locked;
00073 }
00074 
00075 void MutexImpl::Unlock() {
00076   locked_ = false;
00077   released_.SignalAll();
00078   std_mutex_.unlock();
00079 }
00080 
00081 CondVarImpl::CondVarImpl() {}
00082 
00083 CondVarImpl::~CondVarImpl() {}
00084 
00085 void CondVarImpl::Signal() { std_cv_.notify_one(); }
00086 
00087 void CondVarImpl::SignalAll() { std_cv_.notify_all(); }
00088 
00089 void CondVarImpl::Wait(MutexImpl* mu) {
00090   mu->released_.SignalAll();
00091   std_cv_.wait(mu->std_mutex_);
00092 }
00093 
00094 bool CondVarImpl::WaitWithDeadline(MutexImpl* mu, absl::Time deadline) {
00095   mu->released_.SignalAll();
00096   time_t when = ToTimeT(deadline);
00097   int64_t nanos = ToInt64Nanoseconds(deadline - absl::FromTimeT(when));
00098   std::chrono::system_clock::time_point deadline_tp =
00099       std::chrono::system_clock::from_time_t(when) +
00100       std::chrono::duration_cast<std::chrono::system_clock::duration>(
00101           std::chrono::nanoseconds(nanos));
00102   auto deadline_since_epoch =
00103       std::chrono::duration_cast<std::chrono::duration<double>>(
00104           deadline_tp - std::chrono::system_clock::from_time_t(0));
00105   return std_cv_.wait_until(mu->std_mutex_, deadline_tp) ==
00106          std::cv_status::timeout;
00107 }
00108 
00109 #else  // ! _WIN32
00110 
00111 MutexImpl::MutexImpl() {
00112   ABSL_RAW_CHECK(pthread_mutex_init(&pthread_mutex_, nullptr) == 0,
00113                  "pthread error");
00114 }
00115 
00116 MutexImpl::~MutexImpl() {
00117   if (locked_) {
00118     ABSL_RAW_CHECK(pthread_mutex_unlock(&pthread_mutex_) == 0, "pthread error");
00119   }
00120   ABSL_RAW_CHECK(pthread_mutex_destroy(&pthread_mutex_) == 0, "pthread error");
00121 }
00122 
00123 void MutexImpl::Lock() {
00124   ABSL_RAW_CHECK(pthread_mutex_lock(&pthread_mutex_) == 0, "pthread error");
00125   locked_ = true;
00126 }
00127 
00128 bool MutexImpl::TryLock() {
00129   bool locked = (0 == pthread_mutex_trylock(&pthread_mutex_));
00130   if (locked) locked_ = true;
00131   return locked;
00132 }
00133 
00134 void MutexImpl::Unlock() {
00135   locked_ = false;
00136   released_.SignalAll();
00137   ABSL_RAW_CHECK(pthread_mutex_unlock(&pthread_mutex_) == 0, "pthread error");
00138 }
00139 
00140 CondVarImpl::CondVarImpl() {
00141   ABSL_RAW_CHECK(pthread_cond_init(&pthread_cv_, nullptr) == 0,
00142                  "pthread error");
00143 }
00144 
00145 CondVarImpl::~CondVarImpl() {
00146   ABSL_RAW_CHECK(pthread_cond_destroy(&pthread_cv_) == 0, "pthread error");
00147 }
00148 
00149 void CondVarImpl::Signal() {
00150   ABSL_RAW_CHECK(pthread_cond_signal(&pthread_cv_) == 0, "pthread error");
00151 }
00152 
00153 void CondVarImpl::SignalAll() {
00154   ABSL_RAW_CHECK(pthread_cond_broadcast(&pthread_cv_) == 0, "pthread error");
00155 }
00156 
00157 void CondVarImpl::Wait(MutexImpl* mu) {
00158   mu->released_.SignalAll();
00159   ABSL_RAW_CHECK(pthread_cond_wait(&pthread_cv_, &mu->pthread_mutex_) == 0,
00160                  "pthread error");
00161 }
00162 
00163 bool CondVarImpl::WaitWithDeadline(MutexImpl* mu, absl::Time deadline) {
00164   mu->released_.SignalAll();
00165   struct timespec ts = ToTimespec(deadline);
00166   int rc = pthread_cond_timedwait(&pthread_cv_, &mu->pthread_mutex_, &ts);
00167   if (rc == ETIMEDOUT) return true;
00168   ABSL_RAW_CHECK(rc == 0, "pthread error");
00169   return false;
00170 }
00171 
00172 #endif  // ! _WIN32
00173 
00174 void MutexImpl::Await(const Condition& cond) {
00175   if (cond.Eval()) return;
00176   released_.SignalAll();
00177   do {
00178     released_.Wait(this);
00179   } while (!cond.Eval());
00180 }
00181 
00182 bool MutexImpl::AwaitWithDeadline(const Condition& cond, absl::Time deadline) {
00183   if (cond.Eval()) return true;
00184   released_.SignalAll();
00185   while (true) {
00186     if (released_.WaitWithDeadline(this, deadline)) return false;
00187     if (cond.Eval()) return true;
00188   }
00189 }
00190 
00191 }  // namespace synchronization_internal
00192 
00193 Mutex::Mutex() {}
00194 
00195 Mutex::~Mutex() {}
00196 
00197 void Mutex::Lock() { impl()->Lock(); }
00198 
00199 void Mutex::Unlock() { impl()->Unlock(); }
00200 
00201 bool Mutex::TryLock() { return impl()->TryLock(); }
00202 
00203 void Mutex::ReaderLock() { Lock(); }
00204 
00205 void Mutex::ReaderUnlock() { Unlock(); }
00206 
00207 void Mutex::Await(const Condition& cond) { impl()->Await(cond); }
00208 
00209 void Mutex::LockWhen(const Condition& cond) {
00210   Lock();
00211   Await(cond);
00212 }
00213 
00214 bool Mutex::AwaitWithDeadline(const Condition& cond, absl::Time deadline) {
00215   return impl()->AwaitWithDeadline(
00216       cond, synchronization_internal::LimitedDeadline(deadline));
00217 }
00218 
00219 bool Mutex::AwaitWithTimeout(const Condition& cond, absl::Duration timeout) {
00220   return AwaitWithDeadline(
00221       cond, synchronization_internal::DeadlineFromTimeout(timeout));
00222 }
00223 
00224 bool Mutex::LockWhenWithDeadline(const Condition& cond, absl::Time deadline) {
00225   Lock();
00226   return AwaitWithDeadline(cond, deadline);
00227 }
00228 
00229 bool Mutex::LockWhenWithTimeout(const Condition& cond, absl::Duration timeout) {
00230   return LockWhenWithDeadline(
00231       cond, synchronization_internal::DeadlineFromTimeout(timeout));
00232 }
00233 
00234 void Mutex::ReaderLockWhen(const Condition& cond) {
00235   ReaderLock();
00236   Await(cond);
00237 }
00238 
00239 bool Mutex::ReaderLockWhenWithTimeout(const Condition& cond,
00240                                       absl::Duration timeout) {
00241   return LockWhenWithTimeout(cond, timeout);
00242 }
00243 bool Mutex::ReaderLockWhenWithDeadline(const Condition& cond,
00244                                        absl::Time deadline) {
00245   return LockWhenWithDeadline(cond, deadline);
00246 }
00247 
00248 void Mutex::EnableDebugLog(const char*) {}
00249 void Mutex::EnableInvariantDebugging(void (*)(void*), void*) {}
00250 void Mutex::ForgetDeadlockInfo() {}
00251 void Mutex::AssertHeld() const {}
00252 void Mutex::AssertReaderHeld() const {}
00253 void Mutex::AssertNotHeld() const {}
00254 
00255 CondVar::CondVar() {}
00256 
00257 CondVar::~CondVar() {}
00258 
00259 void CondVar::Signal() { impl()->Signal(); }
00260 
00261 void CondVar::SignalAll() { impl()->SignalAll(); }
00262 
00263 void CondVar::Wait(Mutex* mu) { return impl()->Wait(mu->impl()); }
00264 
00265 bool CondVar::WaitWithDeadline(Mutex* mu, absl::Time deadline) {
00266   return impl()->WaitWithDeadline(
00267       mu->impl(), synchronization_internal::LimitedDeadline(deadline));
00268 }
00269 
00270 bool CondVar::WaitWithTimeout(Mutex* mu, absl::Duration timeout) {
00271   return WaitWithDeadline(mu, absl::Now() + timeout);
00272 }
00273 
00274 void CondVar::EnableDebugLog(const char*) {}
00275 
00276 #ifdef THREAD_SANITIZER
00277 extern "C" void __tsan_read1(void *addr);
00278 #else
00279 #define __tsan_read1(addr)  // do nothing if TSan not enabled
00280 #endif
00281 
00282 // A function that just returns its argument, dereferenced
00283 static bool Dereference(void *arg) {
00284   // ThreadSanitizer does not instrument this file for memory accesses.
00285   // This function dereferences a user variable that can participate
00286   // in a data race, so we need to manually tell TSan about this memory access.
00287   __tsan_read1(arg);
00288   return *(static_cast<bool *>(arg));
00289 }
00290 
00291 Condition::Condition() {}   // null constructor, used for kTrue only
00292 const Condition Condition::kTrue;
00293 
00294 Condition::Condition(bool (*func)(void *), void *arg)
00295     : eval_(&CallVoidPtrFunction),
00296       function_(func),
00297       method_(nullptr),
00298       arg_(arg) {}
00299 
00300 bool Condition::CallVoidPtrFunction(const Condition *c) {
00301   return (*c->function_)(c->arg_);
00302 }
00303 
00304 Condition::Condition(const bool *cond)
00305     : eval_(CallVoidPtrFunction),
00306       function_(Dereference),
00307       method_(nullptr),
00308       // const_cast is safe since Dereference does not modify arg
00309       arg_(const_cast<bool *>(cond)) {}
00310 
00311 bool Condition::Eval() const {
00312   // eval_ == null for kTrue
00313   return (this->eval_ == nullptr) || (*this->eval_)(this);
00314 }
00315 
00316 void RegisterSymbolizer(bool (*)(const void*, char*, int)) {}
00317 
00318 }  // namespace absl


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:15