| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 | 
							- // Copyright 2017 The Abseil 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
 
- //
 
- // Unless required by applicable law or agreed to in writing, software
 
- // distributed under the License is distributed on an "AS IS" BASIS,
 
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
- // See the License for the specific language governing permissions and
 
- // limitations under the License.
 
- // Implementation of a small subset of Mutex and CondVar functionality
 
- // for platforms where the production implementation hasn't been fully
 
- // ported yet.
 
- #include "absl/synchronization/mutex.h"
 
- #if defined(_WIN32)
 
- #include <chrono>  // NOLINT(build/c++11)
 
- #else
 
- #include <sys/time.h>
 
- #include <time.h>
 
- #endif
 
- #include <algorithm>
 
- #include "absl/base/internal/raw_logging.h"
 
- #include "absl/time/time.h"
 
- namespace absl {
 
- namespace synchronization_internal {
 
- namespace {
 
- // Return the current time plus the timeout.
 
- absl::Time DeadlineFromTimeout(absl::Duration timeout) {
 
-   return absl::Now() + timeout;
 
- }
 
- // Limit the deadline to a positive, 32-bit time_t value to accommodate
 
- // implementation restrictions.  This also deals with InfinitePast and
 
- // InfiniteFuture.
 
- absl::Time LimitedDeadline(absl::Time deadline) {
 
-   deadline = std::max(absl::FromTimeT(0), deadline);
 
-   deadline = std::min(deadline, absl::FromTimeT(0x7fffffff));
 
-   return deadline;
 
- }
 
- }  // namespace
 
- #if defined(_WIN32)
 
- MutexImpl::MutexImpl() {}
 
- MutexImpl::~MutexImpl() {
 
-   if (locked_) {
 
-     std_mutex_.unlock();
 
-   }
 
- }
 
- void MutexImpl::Lock() {
 
-   std_mutex_.lock();
 
-   locked_ = true;
 
- }
 
- bool MutexImpl::TryLock() {
 
-   bool locked = std_mutex_.try_lock();
 
-   if (locked) locked_ = true;
 
-   return locked;
 
- }
 
- void MutexImpl::Unlock() {
 
-   locked_ = false;
 
-   released_.SignalAll();
 
-   std_mutex_.unlock();
 
- }
 
- CondVarImpl::CondVarImpl() {}
 
- CondVarImpl::~CondVarImpl() {}
 
- void CondVarImpl::Signal() { std_cv_.notify_one(); }
 
- void CondVarImpl::SignalAll() { std_cv_.notify_all(); }
 
- void CondVarImpl::Wait(MutexImpl* mu) {
 
-   mu->released_.SignalAll();
 
-   std_cv_.wait(mu->std_mutex_);
 
- }
 
- bool CondVarImpl::WaitWithDeadline(MutexImpl* mu, absl::Time deadline) {
 
-   mu->released_.SignalAll();
 
-   time_t when = ToTimeT(deadline);
 
-   int64_t nanos = ToInt64Nanoseconds(deadline - absl::FromTimeT(when));
 
-   std::chrono::system_clock::time_point deadline_tp =
 
-       std::chrono::system_clock::from_time_t(when) +
 
-       std::chrono::duration_cast<std::chrono::system_clock::duration>(
 
-           std::chrono::nanoseconds(nanos));
 
-   auto deadline_since_epoch =
 
-       std::chrono::duration_cast<std::chrono::duration<double>>(
 
-           deadline_tp - std::chrono::system_clock::from_time_t(0));
 
-   return std_cv_.wait_until(mu->std_mutex_, deadline_tp) ==
 
-          std::cv_status::timeout;
 
- }
 
- #else  // ! _WIN32
 
- MutexImpl::MutexImpl() {
 
-   ABSL_RAW_CHECK(pthread_mutex_init(&pthread_mutex_, nullptr) == 0,
 
-                  "pthread error");
 
- }
 
- MutexImpl::~MutexImpl() {
 
-   if (locked_) {
 
-     ABSL_RAW_CHECK(pthread_mutex_unlock(&pthread_mutex_) == 0, "pthread error");
 
-   }
 
-   ABSL_RAW_CHECK(pthread_mutex_destroy(&pthread_mutex_) == 0, "pthread error");
 
- }
 
- void MutexImpl::Lock() {
 
-   ABSL_RAW_CHECK(pthread_mutex_lock(&pthread_mutex_) == 0, "pthread error");
 
-   locked_ = true;
 
- }
 
- bool MutexImpl::TryLock() {
 
-   bool locked = (0 == pthread_mutex_trylock(&pthread_mutex_));
 
-   if (locked) locked_ = true;
 
-   return locked;
 
- }
 
- void MutexImpl::Unlock() {
 
-   locked_ = false;
 
-   released_.SignalAll();
 
-   ABSL_RAW_CHECK(pthread_mutex_unlock(&pthread_mutex_) == 0, "pthread error");
 
- }
 
- CondVarImpl::CondVarImpl() {
 
-   ABSL_RAW_CHECK(pthread_cond_init(&pthread_cv_, nullptr) == 0,
 
-                  "pthread error");
 
- }
 
- CondVarImpl::~CondVarImpl() {
 
-   ABSL_RAW_CHECK(pthread_cond_destroy(&pthread_cv_) == 0, "pthread error");
 
- }
 
- void CondVarImpl::Signal() {
 
-   ABSL_RAW_CHECK(pthread_cond_signal(&pthread_cv_) == 0, "pthread error");
 
- }
 
- void CondVarImpl::SignalAll() {
 
-   ABSL_RAW_CHECK(pthread_cond_broadcast(&pthread_cv_) == 0, "pthread error");
 
- }
 
- void CondVarImpl::Wait(MutexImpl* mu) {
 
-   mu->released_.SignalAll();
 
-   ABSL_RAW_CHECK(pthread_cond_wait(&pthread_cv_, &mu->pthread_mutex_) == 0,
 
-                  "pthread error");
 
- }
 
- bool CondVarImpl::WaitWithDeadline(MutexImpl* mu, absl::Time deadline) {
 
-   mu->released_.SignalAll();
 
-   struct timespec ts = ToTimespec(deadline);
 
-   int rc = pthread_cond_timedwait(&pthread_cv_, &mu->pthread_mutex_, &ts);
 
-   if (rc == ETIMEDOUT) return true;
 
-   ABSL_RAW_CHECK(rc == 0, "pthread error");
 
-   return false;
 
- }
 
- #endif  // ! _WIN32
 
- void MutexImpl::Await(const Condition& cond) {
 
-   if (cond.Eval()) return;
 
-   released_.SignalAll();
 
-   do {
 
-     released_.Wait(this);
 
-   } while (!cond.Eval());
 
- }
 
- bool MutexImpl::AwaitWithDeadline(const Condition& cond, absl::Time deadline) {
 
-   if (cond.Eval()) return true;
 
-   released_.SignalAll();
 
-   while (true) {
 
-     if (released_.WaitWithDeadline(this, deadline)) return false;
 
-     if (cond.Eval()) return true;
 
-   }
 
- }
 
- }  // namespace synchronization_internal
 
- Mutex::Mutex() {}
 
- Mutex::~Mutex() {}
 
- void Mutex::Lock() { impl()->Lock(); }
 
- void Mutex::Unlock() { impl()->Unlock(); }
 
- bool Mutex::TryLock() { return impl()->TryLock(); }
 
- void Mutex::ReaderLock() { Lock(); }
 
- void Mutex::ReaderUnlock() { Unlock(); }
 
- void Mutex::Await(const Condition& cond) { impl()->Await(cond); }
 
- void Mutex::LockWhen(const Condition& cond) {
 
-   Lock();
 
-   Await(cond);
 
- }
 
- bool Mutex::AwaitWithDeadline(const Condition& cond, absl::Time deadline) {
 
-   return impl()->AwaitWithDeadline(
 
-       cond, synchronization_internal::LimitedDeadline(deadline));
 
- }
 
- bool Mutex::AwaitWithTimeout(const Condition& cond, absl::Duration timeout) {
 
-   return AwaitWithDeadline(
 
-       cond, synchronization_internal::DeadlineFromTimeout(timeout));
 
- }
 
- bool Mutex::LockWhenWithDeadline(const Condition& cond, absl::Time deadline) {
 
-   Lock();
 
-   return AwaitWithDeadline(cond, deadline);
 
- }
 
- bool Mutex::LockWhenWithTimeout(const Condition& cond, absl::Duration timeout) {
 
-   return LockWhenWithDeadline(
 
-       cond, synchronization_internal::DeadlineFromTimeout(timeout));
 
- }
 
- void Mutex::ReaderLockWhen(const Condition& cond) {
 
-   ReaderLock();
 
-   Await(cond);
 
- }
 
- bool Mutex::ReaderLockWhenWithTimeout(const Condition& cond,
 
-                                       absl::Duration timeout) {
 
-   return LockWhenWithTimeout(cond, timeout);
 
- }
 
- bool Mutex::ReaderLockWhenWithDeadline(const Condition& cond,
 
-                                        absl::Time deadline) {
 
-   return LockWhenWithDeadline(cond, deadline);
 
- }
 
- void Mutex::EnableDebugLog(const char*) {}
 
- void Mutex::EnableInvariantDebugging(void (*)(void*), void*) {}
 
- void Mutex::ForgetDeadlockInfo() {}
 
- void Mutex::AssertHeld() const {}
 
- void Mutex::AssertReaderHeld() const {}
 
- void Mutex::AssertNotHeld() const {}
 
- CondVar::CondVar() {}
 
- CondVar::~CondVar() {}
 
- void CondVar::Signal() { impl()->Signal(); }
 
- void CondVar::SignalAll() { impl()->SignalAll(); }
 
- void CondVar::Wait(Mutex* mu) { return impl()->Wait(mu->impl()); }
 
- bool CondVar::WaitWithDeadline(Mutex* mu, absl::Time deadline) {
 
-   return impl()->WaitWithDeadline(
 
-       mu->impl(), synchronization_internal::LimitedDeadline(deadline));
 
- }
 
- bool CondVar::WaitWithTimeout(Mutex* mu, absl::Duration timeout) {
 
-   return WaitWithDeadline(mu, absl::Now() + timeout);
 
- }
 
- void CondVar::EnableDebugLog(const char*) {}
 
- #ifdef THREAD_SANITIZER
 
- extern "C" void __tsan_read1(void *addr);
 
- #else
 
- #define __tsan_read1(addr)  // do nothing if TSan not enabled
 
- #endif
 
- // A function that just returns its argument, dereferenced
 
- static bool Dereference(void *arg) {
 
-   // ThreadSanitizer does not instrument this file for memory accesses.
 
-   // This function dereferences a user variable that can participate
 
-   // in a data race, so we need to manually tell TSan about this memory access.
 
-   __tsan_read1(arg);
 
-   return *(static_cast<bool *>(arg));
 
- }
 
- Condition::Condition() {}   // null constructor, used for kTrue only
 
- const Condition Condition::kTrue;
 
- Condition::Condition(bool (*func)(void *), void *arg)
 
-     : eval_(&CallVoidPtrFunction),
 
-       function_(func),
 
-       method_(nullptr),
 
-       arg_(arg) {}
 
- bool Condition::CallVoidPtrFunction(const Condition *c) {
 
-   return (*c->function_)(c->arg_);
 
- }
 
- Condition::Condition(const bool *cond)
 
-     : eval_(CallVoidPtrFunction),
 
-       function_(Dereference),
 
-       method_(nullptr),
 
-       // const_cast is safe since Dereference does not modify arg
 
-       arg_(const_cast<bool *>(cond)) {}
 
- bool Condition::Eval() const {
 
-   // eval_ == null for kTrue
 
-   return (this->eval_ == nullptr) || (*this->eval_)(this);
 
- }
 
- void RegisterSymbolizer(bool (*)(const void*, char*, int)) {}
 
- }  // namespace absl
 
 
  |