Repo created
This commit is contained in:
parent
81b91f4139
commit
f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* Copyright 2015 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "rtc_base/deprecated/recursive_critical_section.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/platform_thread_types.h"
|
||||
#include "rtc_base/synchronization/yield.h"
|
||||
#include "rtc_base/system/unused.h"
|
||||
|
||||
#if RTC_DCHECK_IS_ON
|
||||
#define RTC_CS_DEBUG_CODE(x) x
|
||||
#else // !RTC_DCHECK_IS_ON
|
||||
#define RTC_CS_DEBUG_CODE(x)
|
||||
#endif // !RTC_DCHECK_IS_ON
|
||||
|
||||
namespace rtc {
|
||||
|
||||
RecursiveCriticalSection::RecursiveCriticalSection() {
|
||||
#if defined(WEBRTC_WIN)
|
||||
InitializeCriticalSection(&crit_);
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
#if defined(WEBRTC_MAC) && !RTC_USE_NATIVE_MUTEX_ON_MAC
|
||||
lock_queue_ = 0;
|
||||
owning_thread_ = 0;
|
||||
recursion_ = 0;
|
||||
semaphore_ = dispatch_semaphore_create(0);
|
||||
#else
|
||||
pthread_mutexattr_t mutex_attribute;
|
||||
pthread_mutexattr_init(&mutex_attribute);
|
||||
pthread_mutexattr_settype(&mutex_attribute, PTHREAD_MUTEX_RECURSIVE);
|
||||
#if defined(WEBRTC_MAC)
|
||||
pthread_mutexattr_setpolicy_np(&mutex_attribute,
|
||||
_PTHREAD_MUTEX_POLICY_FIRSTFIT);
|
||||
#endif
|
||||
pthread_mutex_init(&mutex_, &mutex_attribute);
|
||||
pthread_mutexattr_destroy(&mutex_attribute);
|
||||
#endif
|
||||
RTC_CS_DEBUG_CODE(thread_ = 0);
|
||||
RTC_CS_DEBUG_CODE(recursion_count_ = 0);
|
||||
RTC_UNUSED(thread_);
|
||||
RTC_UNUSED(recursion_count_);
|
||||
#else
|
||||
#error Unsupported platform.
|
||||
#endif
|
||||
}
|
||||
|
||||
RecursiveCriticalSection::~RecursiveCriticalSection() {
|
||||
#if defined(WEBRTC_WIN)
|
||||
DeleteCriticalSection(&crit_);
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
#if defined(WEBRTC_MAC) && !RTC_USE_NATIVE_MUTEX_ON_MAC
|
||||
dispatch_release(semaphore_);
|
||||
#else
|
||||
pthread_mutex_destroy(&mutex_);
|
||||
#endif
|
||||
#else
|
||||
#error Unsupported platform.
|
||||
#endif
|
||||
}
|
||||
|
||||
void RecursiveCriticalSection::Enter() const RTC_EXCLUSIVE_LOCK_FUNCTION() {
|
||||
#if defined(WEBRTC_WIN)
|
||||
EnterCriticalSection(&crit_);
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
#if defined(WEBRTC_MAC) && !RTC_USE_NATIVE_MUTEX_ON_MAC
|
||||
int spin = 3000;
|
||||
PlatformThreadRef self = CurrentThreadRef();
|
||||
bool have_lock = false;
|
||||
do {
|
||||
// Instead of calling TryEnter() in this loop, we do two interlocked
|
||||
// operations, first a read-only one in order to avoid affecting the lock
|
||||
// cache-line while spinning, in case another thread is using the lock.
|
||||
if (!IsThreadRefEqual(owning_thread_, self)) {
|
||||
if (AtomicOps::AcquireLoad(&lock_queue_) == 0) {
|
||||
if (AtomicOps::CompareAndSwap(&lock_queue_, 0, 1) == 0) {
|
||||
have_lock = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
AtomicOps::Increment(&lock_queue_);
|
||||
have_lock = true;
|
||||
break;
|
||||
}
|
||||
|
||||
sched_yield();
|
||||
} while (--spin);
|
||||
|
||||
if (!have_lock && AtomicOps::Increment(&lock_queue_) > 1) {
|
||||
// Owning thread cannot be the current thread since TryEnter() would
|
||||
// have succeeded.
|
||||
RTC_DCHECK(!IsThreadRefEqual(owning_thread_, self));
|
||||
// Wait for the lock to become available.
|
||||
dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);
|
||||
RTC_DCHECK(owning_thread_ == 0);
|
||||
RTC_DCHECK(!recursion_);
|
||||
}
|
||||
|
||||
owning_thread_ = self;
|
||||
++recursion_;
|
||||
|
||||
#else
|
||||
pthread_mutex_lock(&mutex_);
|
||||
#endif
|
||||
|
||||
#if RTC_DCHECK_IS_ON
|
||||
if (!recursion_count_) {
|
||||
RTC_DCHECK(!thread_);
|
||||
thread_ = CurrentThreadRef();
|
||||
} else {
|
||||
RTC_DCHECK(CurrentThreadIsOwner());
|
||||
}
|
||||
++recursion_count_;
|
||||
#endif
|
||||
#else
|
||||
#error Unsupported platform.
|
||||
#endif
|
||||
}
|
||||
|
||||
bool RecursiveCriticalSection::TryEnter() const
|
||||
RTC_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
|
||||
#if defined(WEBRTC_WIN)
|
||||
return TryEnterCriticalSection(&crit_) != FALSE;
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
#if defined(WEBRTC_MAC) && !RTC_USE_NATIVE_MUTEX_ON_MAC
|
||||
if (!IsThreadRefEqual(owning_thread_, CurrentThreadRef())) {
|
||||
if (AtomicOps::CompareAndSwap(&lock_queue_, 0, 1) != 0)
|
||||
return false;
|
||||
owning_thread_ = CurrentThreadRef();
|
||||
RTC_DCHECK(!recursion_);
|
||||
} else {
|
||||
AtomicOps::Increment(&lock_queue_);
|
||||
}
|
||||
++recursion_;
|
||||
#else
|
||||
if (pthread_mutex_trylock(&mutex_) != 0)
|
||||
return false;
|
||||
#endif
|
||||
#if RTC_DCHECK_IS_ON
|
||||
if (!recursion_count_) {
|
||||
RTC_DCHECK(!thread_);
|
||||
thread_ = CurrentThreadRef();
|
||||
} else {
|
||||
RTC_DCHECK(CurrentThreadIsOwner());
|
||||
}
|
||||
++recursion_count_;
|
||||
#endif
|
||||
return true;
|
||||
#else
|
||||
#error Unsupported platform.
|
||||
#endif
|
||||
}
|
||||
|
||||
void RecursiveCriticalSection::Leave() const RTC_UNLOCK_FUNCTION() {
|
||||
RTC_DCHECK(CurrentThreadIsOwner());
|
||||
#if defined(WEBRTC_WIN)
|
||||
LeaveCriticalSection(&crit_);
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
#if RTC_DCHECK_IS_ON
|
||||
--recursion_count_;
|
||||
RTC_DCHECK(recursion_count_ >= 0);
|
||||
if (!recursion_count_)
|
||||
thread_ = 0;
|
||||
#endif
|
||||
#if defined(WEBRTC_MAC) && !RTC_USE_NATIVE_MUTEX_ON_MAC
|
||||
RTC_DCHECK(IsThreadRefEqual(owning_thread_, CurrentThreadRef()));
|
||||
RTC_DCHECK_GE(recursion_, 0);
|
||||
--recursion_;
|
||||
if (!recursion_)
|
||||
owning_thread_ = 0;
|
||||
|
||||
if (AtomicOps::Decrement(&lock_queue_) > 0 && !recursion_)
|
||||
dispatch_semaphore_signal(semaphore_);
|
||||
#else
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
#endif
|
||||
#else
|
||||
#error Unsupported platform.
|
||||
#endif
|
||||
}
|
||||
|
||||
bool RecursiveCriticalSection::CurrentThreadIsOwner() const {
|
||||
#if defined(WEBRTC_WIN)
|
||||
// OwningThread has type HANDLE but actually contains the Thread ID:
|
||||
// http://stackoverflow.com/questions/12675301/why-is-the-owningthread-member-of-critical-section-of-type-handle-when-it-is-de
|
||||
// Converting through size_t avoids the VS 2015 warning C4312: conversion from
|
||||
// 'type1' to 'type2' of greater size
|
||||
return crit_.OwningThread ==
|
||||
reinterpret_cast<HANDLE>(static_cast<size_t>(GetCurrentThreadId()));
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
#if RTC_DCHECK_IS_ON
|
||||
return IsThreadRefEqual(thread_, CurrentThreadRef());
|
||||
#else
|
||||
return true;
|
||||
#endif // RTC_DCHECK_IS_ON
|
||||
#else
|
||||
#error Unsupported platform.
|
||||
#endif
|
||||
}
|
||||
|
||||
CritScope::CritScope(const RecursiveCriticalSection* cs) : cs_(cs) {
|
||||
cs_->Enter();
|
||||
}
|
||||
CritScope::~CritScope() {
|
||||
cs_->Leave();
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef RTC_BASE_DEPRECATED_RECURSIVE_CRITICAL_SECTION_H_
|
||||
#define RTC_BASE_DEPRECATED_RECURSIVE_CRITICAL_SECTION_H_
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "rtc_base/platform_thread_types.h"
|
||||
#include "rtc_base/thread_annotations.h"
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
// clang-format off
|
||||
// clang formating would change include order.
|
||||
|
||||
// Include winsock2.h before including <windows.h> to maintain consistency with
|
||||
// win32.h. To include win32.h directly, it must be broken out into its own
|
||||
// build target.
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <sal.h> // must come after windows headers.
|
||||
// clang-format on
|
||||
#endif // defined(WEBRTC_WIN)
|
||||
|
||||
#if defined(WEBRTC_POSIX)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
// See notes in the 'Performance' unit test for the effects of this flag.
|
||||
#define RTC_USE_NATIVE_MUTEX_ON_MAC 1
|
||||
|
||||
#if defined(WEBRTC_MAC) && !RTC_USE_NATIVE_MUTEX_ON_MAC
|
||||
#include <dispatch/dispatch.h>
|
||||
#endif
|
||||
|
||||
namespace rtc {
|
||||
|
||||
// NOTE: This class is deprecated. Please use webrtc::Mutex instead!
|
||||
// Search using https://www.google.com/?q=recursive+lock+considered+harmful
|
||||
// to find the reasons.
|
||||
//
|
||||
// Locking methods (Enter, TryEnter, Leave)are const to permit protecting
|
||||
// members inside a const context without requiring mutable
|
||||
// RecursiveCriticalSections everywhere. RecursiveCriticalSection is
|
||||
// reentrant lock.
|
||||
class RTC_LOCKABLE RecursiveCriticalSection {
|
||||
public:
|
||||
RecursiveCriticalSection();
|
||||
~RecursiveCriticalSection();
|
||||
|
||||
void Enter() const RTC_EXCLUSIVE_LOCK_FUNCTION();
|
||||
bool TryEnter() const RTC_EXCLUSIVE_TRYLOCK_FUNCTION(true);
|
||||
void Leave() const RTC_UNLOCK_FUNCTION();
|
||||
|
||||
private:
|
||||
// Use only for RTC_DCHECKing.
|
||||
bool CurrentThreadIsOwner() const;
|
||||
|
||||
#if defined(WEBRTC_WIN)
|
||||
mutable CRITICAL_SECTION crit_;
|
||||
#elif defined(WEBRTC_POSIX)
|
||||
#if defined(WEBRTC_MAC) && !RTC_USE_NATIVE_MUTEX_ON_MAC
|
||||
// Number of times the lock has been locked + number of threads waiting.
|
||||
// TODO(tommi): We could use this number and subtract the recursion count
|
||||
// to find places where we have multiple threads contending on the same lock.
|
||||
mutable std::atomic<int> lock_queue_;
|
||||
// `recursion_` represents the recursion count + 1 for the thread that owns
|
||||
// the lock. Only modified by the thread that owns the lock.
|
||||
mutable int recursion_;
|
||||
// Used to signal a single waiting thread when the lock becomes available.
|
||||
mutable dispatch_semaphore_t semaphore_;
|
||||
// The thread that currently holds the lock. Required to handle recursion.
|
||||
mutable PlatformThreadRef owning_thread_;
|
||||
#else
|
||||
mutable pthread_mutex_t mutex_;
|
||||
#endif
|
||||
mutable PlatformThreadRef thread_; // Only used by RTC_DCHECKs.
|
||||
mutable int recursion_count_; // Only used by RTC_DCHECKs.
|
||||
#else // !defined(WEBRTC_WIN) && !defined(WEBRTC_POSIX)
|
||||
#error Unsupported platform.
|
||||
#endif
|
||||
};
|
||||
|
||||
// CritScope, for serializing execution through a scope.
|
||||
class RTC_SCOPED_LOCKABLE CritScope {
|
||||
public:
|
||||
explicit CritScope(const RecursiveCriticalSection* cs)
|
||||
RTC_EXCLUSIVE_LOCK_FUNCTION(cs);
|
||||
~CritScope() RTC_UNLOCK_FUNCTION();
|
||||
|
||||
CritScope(const CritScope&) = delete;
|
||||
CritScope& operator=(const CritScope&) = delete;
|
||||
|
||||
private:
|
||||
const RecursiveCriticalSection* const cs_;
|
||||
};
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // RTC_BASE_DEPRECATED_RECURSIVE_CRITICAL_SECTION_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue