Some style fixes.

Refactors the rw lock implementation.

BUG=N/A

Review URL: https://webrtc-codereview.appspot.com/797004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2822 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
henrike@webrtc.org 2012-09-25 20:27:51 +00:00
parent b6cceb8b92
commit 9f84723725
9 changed files with 205 additions and 352 deletions

View File

@ -16,20 +16,18 @@
// functionality and will therefore have worse performance. // functionality and will therefore have worse performance.
namespace webrtc { namespace webrtc {
class RWLockWrapper class RWLockWrapper
{ {
public: public:
static RWLockWrapper* CreateRWLock(); static RWLockWrapper* CreateRWLock();
virtual ~RWLockWrapper(); virtual ~RWLockWrapper() {}
virtual void AcquireLockExclusive() = 0; virtual void AcquireLockExclusive() = 0;
virtual void ReleaseLockExclusive() = 0; virtual void ReleaseLockExclusive() = 0;
virtual void AcquireLockShared() = 0; virtual void AcquireLockShared() = 0;
virtual void ReleaseLockShared() = 0; virtual void ReleaseLockShared() = 0;
protected:
virtual int Init() = 0;
}; };
// RAII extensions of the RW lock. Prevents Acquire/Release missmatches and // RAII extensions of the RW lock. Prevents Acquire/Release missmatches and
@ -71,6 +69,7 @@ public:
private: private:
RWLockWrapper& _rwLock; RWLockWrapper& _rwLock;
}; };
} // namespace webrtc } // namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_RW_LOCK_WRAPPER_H_ #endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_RW_LOCK_WRAPPER_H_

View File

@ -13,29 +13,25 @@
#include <assert.h> #include <assert.h>
#if defined(_WIN32) #if defined(_WIN32)
#include "rw_lock_win.h" #include "rw_lock_generic.h"
#include "rw_lock_win.h"
#else #else
#include "rw_lock_posix.h" #include "rw_lock_posix.h"
#endif #endif
namespace webrtc { namespace webrtc {
RWLockWrapper* RWLockWrapper::CreateRWLock()
{ RWLockWrapper* RWLockWrapper::CreateRWLock() {
#ifdef _WIN32 #ifdef _WIN32
RWLockWrapper* lock = new RWLockWindows(); // Native implementation is faster, so use that if available.
#else RWLockWrapper* lock = RWLockWin::Create();
RWLockWrapper* lock = new RWLockPosix(); if (lock) {
#endif
if(lock->Init() != 0)
{
delete lock;
assert(false);
return NULL;
}
return lock; return lock;
}
return new RWLockGeneric();
#else
return RWLockPosix::Create();
#endif
} }
RWLockWrapper::~RWLockWrapper() } // namespace webrtc
{
}
} // namespace webrtc

View File

@ -8,99 +8,70 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include "rw_lock_generic.h" #include "system_wrappers/source/rw_lock_generic.h"
#include "condition_variable_wrapper.h" #include "system_wrappers/interface/condition_variable_wrapper.h"
#include "critical_section_wrapper.h" #include "system_wrappers/interface/critical_section_wrapper.h"
namespace webrtc { namespace webrtc {
RWLockWrapperGeneric::RWLockWrapperGeneric()
: _readersActive(0), RWLockGeneric::RWLockGeneric()
_writerActive(false), : readers_active_(0),
_readersWaiting(0), writer_active_(false),
_writersWaiting(0) readers_waiting_(0),
{ writers_waiting_(0) {
_critSectPtr = CriticalSectionWrapper::CreateCriticalSection(); critical_section_ = CriticalSectionWrapper::CreateCriticalSection();
_readCondPtr = ConditionVariableWrapper::CreateConditionVariable(); read_condition_ = ConditionVariableWrapper::CreateConditionVariable();
_writeCondPtr = ConditionVariableWrapper::CreateConditionVariable(); write_condition_ = ConditionVariableWrapper::CreateConditionVariable();
} }
RWLockWrapperGeneric::~RWLockWrapperGeneric() RWLockGeneric::~RWLockGeneric() {
{ delete write_condition_;
delete _writeCondPtr; delete read_condition_;
delete _readCondPtr; delete critical_section_;
delete _critSectPtr;
} }
int RWLockWrapperGeneric::Init() void RWLockGeneric::AcquireLockExclusive() {
{ CriticalSectionScoped cs(critical_section_);
return 0; if (writer_active_ || readers_active_ > 0) {
} ++writers_waiting_;
while (writer_active_ || readers_active_ > 0) {
void RWLockWrapperGeneric::AcquireLockExclusive() write_condition_->SleepCS(*critical_section_);
{
_critSectPtr->Enter();
if (_writerActive || _readersActive > 0)
{
++_writersWaiting;
while (_writerActive || _readersActive > 0)
{
_writeCondPtr->SleepCS(*_critSectPtr);
}
--_writersWaiting;
} }
_writerActive = true; --writers_waiting_;
_critSectPtr->Leave(); }
writer_active_ = true;
} }
void RWLockWrapperGeneric::ReleaseLockExclusive() void RWLockGeneric::ReleaseLockExclusive() {
{ CriticalSectionScoped cs(critical_section_);
_critSectPtr->Enter(); writer_active_ = false;
if (writers_waiting_ > 0) {
write_condition_->Wake();
} else if (readers_waiting_ > 0) {
read_condition_->WakeAll();
}
}
_writerActive = false; void RWLockGeneric::AcquireLockShared() {
CriticalSectionScoped cs(critical_section_);
if (writer_active_ || writers_waiting_ > 0) {
++readers_waiting_;
if (_writersWaiting > 0) while (writer_active_ || writers_waiting_ > 0) {
{ read_condition_->SleepCS(*critical_section_);
_writeCondPtr->Wake();
}else if (_readersWaiting > 0)
{
_readCondPtr->WakeAll();
} }
_critSectPtr->Leave(); --readers_waiting_;
}
++readers_active_;
} }
void RWLockWrapperGeneric::AcquireLockShared() void RWLockGeneric::ReleaseLockShared() {
{ CriticalSectionScoped cs(critical_section_);
_critSectPtr->Enter(); --readers_active_;
if (readers_active_ == 0 && writers_waiting_ > 0) {
if (_writerActive || _writersWaiting > 0) write_condition_->Wake();
{ }
++_readersWaiting;
while (_writerActive || _writersWaiting > 0)
{
_readCondPtr->SleepCS(*_critSectPtr);
}
--_readersWaiting;
}
++_readersActive;
_critSectPtr->Leave();
} }
void RWLockWrapperGeneric::ReleaseLockShared() } // namespace webrtc
{
_critSectPtr->Enter();
--_readersActive;
if (_readersActive == 0 && _writersWaiting > 0)
{
_writeCondPtr->Wake();
}
_critSectPtr->Leave();
}
} // namespace webrtc

View File

@ -11,17 +11,17 @@
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_ #ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_ #define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_
#include "rw_lock_wrapper.h" #include "system_wrappers/interface/rw_lock_wrapper.h"
namespace webrtc { namespace webrtc {
class CriticalSectionWrapper; class CriticalSectionWrapper;
class ConditionVariableWrapper; class ConditionVariableWrapper;
class RWLockWrapperGeneric : public RWLockWrapper class RWLockGeneric : public RWLockWrapper {
{
public: public:
RWLockWrapperGeneric(); RWLockGeneric();
virtual ~RWLockWrapperGeneric(); virtual ~RWLockGeneric();
virtual void AcquireLockExclusive(); virtual void AcquireLockExclusive();
virtual void ReleaseLockExclusive(); virtual void ReleaseLockExclusive();
@ -29,18 +29,17 @@ public:
virtual void AcquireLockShared(); virtual void AcquireLockShared();
virtual void ReleaseLockShared(); virtual void ReleaseLockShared();
protected:
virtual int Init();
private: private:
CriticalSectionWrapper* _critSectPtr; CriticalSectionWrapper* critical_section_;
ConditionVariableWrapper* _readCondPtr; ConditionVariableWrapper* read_condition_;
ConditionVariableWrapper* _writeCondPtr; ConditionVariableWrapper* write_condition_;
int _readersActive; int readers_active_;
bool _writerActive; bool writer_active_;
int _readersWaiting; int readers_waiting_;
int _writersWaiting; int writers_waiting_;
}; };
} // namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_ } // namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_GENERIC_H_

View File

@ -8,40 +8,44 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include "rw_lock_posix.h" #include "system_wrappers/source/rw_lock_posix.h"
namespace webrtc { namespace webrtc {
RWLockPosix::RWLockPosix() : _lock()
{ RWLockPosix::RWLockPosix() : _lock() {
} }
RWLockPosix::~RWLockPosix() RWLockPosix::~RWLockPosix() {
{ pthread_rwlock_destroy(&_lock);
pthread_rwlock_destroy(&_lock);
} }
int RWLockPosix::Init() RWLockPosix* RWLockPosix::Create() {
{ RWLockPosix* ret_val = new RWLockPosix();
return pthread_rwlock_init(&_lock, 0); if (!ret_val->Init()) {
delete ret_val;
return NULL;
}
return ret_val;
} }
void RWLockPosix::AcquireLockExclusive() bool RWLockPosix::Init() {
{ return pthread_rwlock_init(&_lock, 0) == 0;
pthread_rwlock_wrlock(&_lock);
} }
void RWLockPosix::ReleaseLockExclusive() void RWLockPosix::AcquireLockExclusive() {
{ pthread_rwlock_wrlock(&_lock);
pthread_rwlock_unlock(&_lock);
} }
void RWLockPosix::AcquireLockShared() void RWLockPosix::ReleaseLockExclusive() {
{ pthread_rwlock_unlock(&_lock);
pthread_rwlock_rdlock(&_lock);
} }
void RWLockPosix::ReleaseLockShared() void RWLockPosix::AcquireLockShared() {
{ pthread_rwlock_rdlock(&_lock);
pthread_rwlock_unlock(&_lock);
} }
} // namespace webrtc
void RWLockPosix::ReleaseLockShared() {
pthread_rwlock_unlock(&_lock);
}
} // namespace webrtc

View File

@ -11,15 +11,16 @@
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_ #ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_ #define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_
#include "rw_lock_wrapper.h" #include "system_wrappers/interface/rw_lock_wrapper.h"
#include <pthread.h> #include <pthread.h>
namespace webrtc { namespace webrtc {
class RWLockPosix : public RWLockWrapper class RWLockPosix : public RWLockWrapper
{ {
public: public:
RWLockPosix(); static RWLockPosix* Create();
virtual ~RWLockPosix(); virtual ~RWLockPosix();
virtual void AcquireLockExclusive(); virtual void AcquireLockExclusive();
@ -28,12 +29,13 @@ public:
virtual void AcquireLockShared(); virtual void AcquireLockShared();
virtual void ReleaseLockShared(); virtual void ReleaseLockShared();
protected:
virtual int Init();
private: private:
RWLockPosix();
bool Init();
pthread_rwlock_t _lock; pthread_rwlock_t _lock;
}; };
} // namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_ } // namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_POSIX_H_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
@ -8,179 +8,90 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include "rw_lock_win.h" #include "system_wrappers/source/rw_lock_win.h"
#include "critical_section_wrapper.h"
#include "condition_variable_wrapper.h"
#include "trace.h" #include "trace.h"
// TODO (hellner) why not just use the rw_lock_generic.cc solution if
// native is not supported? Unnecessary redundancy!
namespace webrtc { namespace webrtc {
bool RWLockWindows::_winSupportRWLockPrimitive = false;
static bool native_rw_locks_supported = false;
static bool module_load_attempted = false;
static HMODULE library = NULL; static HMODULE library = NULL;
PInitializeSRWLock _PInitializeSRWLock; typedef void (WINAPI *InitializeSRWLock)(PSRWLOCK);
PAcquireSRWLockExclusive _PAcquireSRWLockExclusive;
PAcquireSRWLockShared _PAcquireSRWLockShared;
PReleaseSRWLockShared _PReleaseSRWLockShared;
PReleaseSRWLockExclusive _PReleaseSRWLockExclusive;
RWLockWindows::RWLockWindows() typedef void (WINAPI *AcquireSRWLockExclusive)(PSRWLOCK);
: _critSectPtr(NULL), typedef void (WINAPI *ReleaseSRWLockExclusive)(PSRWLOCK);
_readCondPtr(NULL),
_writeCondPtr(NULL), typedef void (WINAPI *AcquireSRWLockShared)(PSRWLOCK);
_readersActive(0), typedef void (WINAPI *ReleaseSRWLockShared)(PSRWLOCK);
_writerActive(false),
_readersWaiting(0), InitializeSRWLock initialize_srw_lock;
_writersWaiting(0) AcquireSRWLockExclusive acquire_srw_lock_exclusive;
{ AcquireSRWLockShared acquire_srw_lock_shared;
ReleaseSRWLockShared release_srw_lock_shared;
ReleaseSRWLockExclusive release_srw_lock_exclusive;
RWLockWin::RWLockWin() {
initialize_srw_lock(&lock_);
} }
RWLockWindows::~RWLockWindows() RWLockWin* RWLockWin::Create() {
{ if (!LoadModule()) {
delete _writeCondPtr; return NULL;
delete _readCondPtr; }
delete _critSectPtr; return new RWLockWin();
} }
int RWLockWindows::Init() void RWLockWin::AcquireLockExclusive() {
{ acquire_srw_lock_exclusive(&lock_);
if(!library)
{
// Use native implementation if supported (i.e Vista+)
library = LoadLibrary(TEXT("Kernel32.dll"));
if(library)
{
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
"Loaded Kernel.dll");
_PInitializeSRWLock =
(PInitializeSRWLock)GetProcAddress(
library,
"InitializeSRWLock");
_PAcquireSRWLockExclusive =
(PAcquireSRWLockExclusive)GetProcAddress(
library,
"AcquireSRWLockExclusive");
_PReleaseSRWLockExclusive =
(PReleaseSRWLockExclusive)GetProcAddress(
library,
"ReleaseSRWLockExclusive");
_PAcquireSRWLockShared =
(PAcquireSRWLockShared)GetProcAddress(
library,
"AcquireSRWLockShared");
_PReleaseSRWLockShared =
(PReleaseSRWLockShared)GetProcAddress(
library,
"ReleaseSRWLockShared");
if( _PInitializeSRWLock &&
_PAcquireSRWLockExclusive &&
_PReleaseSRWLockExclusive &&
_PAcquireSRWLockShared &&
_PReleaseSRWLockShared )
{
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
"Loaded Simple RW Lock");
_winSupportRWLockPrimitive = true;
}
}
}
if(_winSupportRWLockPrimitive)
{
_PInitializeSRWLock(&_lock);
} else {
_critSectPtr = CriticalSectionWrapper::CreateCriticalSection();
_readCondPtr = ConditionVariableWrapper::CreateConditionVariable();
_writeCondPtr = ConditionVariableWrapper::CreateConditionVariable();
}
return 0;
} }
void RWLockWindows::AcquireLockExclusive() void RWLockWin::ReleaseLockExclusive() {
{ release_srw_lock_exclusive(&lock_);
if (_winSupportRWLockPrimitive)
{
_PAcquireSRWLockExclusive(&_lock);
} else {
_critSectPtr->Enter();
if (_writerActive || _readersActive > 0)
{
++_writersWaiting;
while (_writerActive || _readersActive > 0)
{
_writeCondPtr->SleepCS(*_critSectPtr);
}
--_writersWaiting;
}
_writerActive = true;
_critSectPtr->Leave();
}
} }
void RWLockWindows::ReleaseLockExclusive() void RWLockWin::AcquireLockShared() {
{ acquire_srw_lock_shared(&lock_);
if(_winSupportRWLockPrimitive)
{
_PReleaseSRWLockExclusive(&_lock);
} else {
_critSectPtr->Enter();
_writerActive = false;
if (_writersWaiting > 0)
{
_writeCondPtr->Wake();
}else if (_readersWaiting > 0) {
_readCondPtr->WakeAll();
}
_critSectPtr->Leave();
}
} }
void RWLockWindows::AcquireLockShared() void RWLockWin::ReleaseLockShared() {
{ release_srw_lock_shared(&lock_);
if(_winSupportRWLockPrimitive)
{
_PAcquireSRWLockShared(&_lock);
} else
{
_critSectPtr->Enter();
if (_writerActive || _writersWaiting > 0)
{
++_readersWaiting;
while (_writerActive || _writersWaiting > 0)
{
_readCondPtr->SleepCS(*_critSectPtr);
}
--_readersWaiting;
}
++_readersActive;
_critSectPtr->Leave();
}
} }
void RWLockWindows::ReleaseLockShared() bool RWLockWin::LoadModule() {
{ if (module_load_attempted) {
if(_winSupportRWLockPrimitive) return native_rw_locks_supported;
{ }
_PReleaseSRWLockShared(&_lock); module_load_attempted = true;
} else // Use native implementation if supported (i.e Vista+)
{ library = LoadLibrary(TEXT("Kernel32.dll"));
_critSectPtr->Enter(); if (!library) {
return false;
}
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Kernel.dll");
--_readersActive; initialize_srw_lock =
(InitializeSRWLock)GetProcAddress(library, "InitializeSRWLock");
if (_readersActive == 0 && _writersWaiting > 0) acquire_srw_lock_exclusive =
{ (AcquireSRWLockExclusive)GetProcAddress(library,
_writeCondPtr->Wake(); "AcquireSRWLockExclusive");
} release_srw_lock_exclusive =
_critSectPtr->Leave(); (ReleaseSRWLockExclusive)GetProcAddress(library,
} "ReleaseSRWLockExclusive");
acquire_srw_lock_shared =
(AcquireSRWLockShared)GetProcAddress(library, "AcquireSRWLockShared");
release_srw_lock_shared =
(ReleaseSRWLockShared)GetProcAddress(library, "ReleaseSRWLockShared");
if (initialize_srw_lock && acquire_srw_lock_exclusive &&
release_srw_lock_exclusive && acquire_srw_lock_shared &&
release_srw_lock_shared) {
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, "Loaded Native RW Lock");
native_rw_locks_supported = true;
}
return native_rw_locks_supported;
} }
} // namespace webrtc
} // namespace webrtc

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
* *
* Use of this source code is governed by a BSD-style license * 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 * that can be found in the LICENSE file in the root of the source
@ -8,64 +8,33 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WINDOWS_H_ #ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WIN__H_
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WINDOWS_H_ #define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WIN__H_
#include "rw_lock_wrapper.h" #include "system_wrappers/interface/rw_lock_wrapper.h"
#include <Windows.h> #include <Windows.h>
#if !defined(RTL_SRWLOCK_INIT)
typedef struct _RTL_SRWLOCK
{
void* Ptr;
} RTL_SRWLOCK, *PRTL_SRWLOCK;
typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
#endif
namespace webrtc { namespace webrtc {
class CriticalSectionWrapper;
class ConditionVariableWrapper;
typedef void (WINAPI *PInitializeSRWLock)(PSRWLOCK); class RWLockWin : public RWLockWrapper {
public:
static RWLockWin* Create();
~RWLockWin() {}
typedef void (WINAPI *PAcquireSRWLockExclusive)(PSRWLOCK); virtual void AcquireLockExclusive();
typedef void (WINAPI *PReleaseSRWLockExclusive)(PSRWLOCK); virtual void ReleaseLockExclusive();
typedef void (WINAPI *PAcquireSRWLockShared)(PSRWLOCK); virtual void AcquireLockShared();
typedef void (WINAPI *PReleaseSRWLockShared)(PSRWLOCK); virtual void ReleaseLockShared();
private:
RWLockWin();
static bool LoadModule();
class RWLockWindows :public RWLockWrapper SRWLOCK lock_;
{
public:
RWLockWindows();
virtual ~RWLockWindows();
virtual void AcquireLockExclusive();
virtual void ReleaseLockExclusive();
virtual void AcquireLockShared();
virtual void ReleaseLockShared();
protected:
virtual int Init();
private:
// For native implementation.
static bool _winSupportRWLockPrimitive;
SRWLOCK _lock;
// Genric implementation, fallback if native is not supported.
CriticalSectionWrapper* _critSectPtr;
ConditionVariableWrapper* _readCondPtr;
ConditionVariableWrapper* _writeCondPtr;
int _readersActive;
bool _writerActive;
int _readersWaiting;
int _writersWaiting;
}; };
} // namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WINDOWS_H_ } // namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WIN__H_

View File

@ -85,6 +85,8 @@
'list_no_stl.cc', 'list_no_stl.cc',
'map.cc', 'map.cc',
'rw_lock.cc', 'rw_lock.cc',
'rw_lock_generic.cc',
'rw_lock_generic.h',
'rw_lock_posix.cc', 'rw_lock_posix.cc',
'rw_lock_posix.h', 'rw_lock_posix.h',
'rw_lock_win.cc', 'rw_lock_win.cc',