diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /APEX_1.4/common/src/ApexRWLockable.cpp | |
| download | physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip | |
Initial commit:
PhysX 3.4.0 Update @ 21294896
APEX 1.4.0 Update @ 21275617
[CL 21300167]
Diffstat (limited to 'APEX_1.4/common/src/ApexRWLockable.cpp')
| -rw-r--r-- | APEX_1.4/common/src/ApexRWLockable.cpp | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/APEX_1.4/common/src/ApexRWLockable.cpp b/APEX_1.4/common/src/ApexRWLockable.cpp new file mode 100644 index 00000000..280a640b --- /dev/null +++ b/APEX_1.4/common/src/ApexRWLockable.cpp @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. + * + * NVIDIA CORPORATION and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA CORPORATION is strictly prohibited. + */ + +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#include "ApexRWLockable.h" +#include "PsThread.h" +#include "PsAtomic.h" +#include "ApexSDKIntl.h" + +namespace nvidia +{ +namespace apex +{ + +ApexRWLockable::ApexRWLockable() + : + mEnabled (true) + , mCurrentWriter(0) + , mRWLock() + , mConcurrentWriteCount (0) + , mConcurrentReadCount (0) + , mConcurrentErrorCount (0) +{ +} + +ApexRWLockable::~ApexRWLockable() +{ +} + +void ApexRWLockable::setEnabled(bool e) +{ + mEnabled = e; +} + +bool ApexRWLockable::isEnabled() const +{ + return mEnabled; +} + +void ApexRWLockable::acquireReadLock(const char*, uint32_t) const +{ + mRWLock.lockReader(); +} + +void ApexRWLockable::acquireWriteLock(const char*, uint32_t) const +{ + mRWLock.lockWriter(); + mCurrentWriter = Thread::getId(); +} + +void ApexRWLockable::releaseReadLock(void) const +{ + mRWLock.unlockReader(); +} + +void ApexRWLockable::releaseWriteLock(void) const +{ + mCurrentWriter = 0; + mRWLock.unlockWriter(); +} + +bool ApexRWLockable::startWrite(bool allowReentry) +{ + PX_COMPILE_TIME_ASSERT(sizeof(ThreadReadWriteCount) == 4); + mDataLock.lock(); + bool error = false; + + ThreadReadWriteCount& rwc = mData[Thread::getId()]; + // check that we are the only thread reading (this allows read->write order on a single thread) + error |= mConcurrentReadCount != rwc.counters.readDepth; + + // check no other threads are writing + error |= mConcurrentWriteCount != rwc.counters.writeDepth; + + // increment shared write counter + shdfnd::atomicIncrement(&mConcurrentWriteCount); + + // in the normal case (re-entry is allowed) then we simply increment + // the writeDepth by 1, otherwise (re-entry is not allowed) increment + // by 2 to force subsequent writes to fail by creating a mismatch between + // the concurrent write counter and the local counter, any value > 1 will do + if (allowReentry) + rwc.counters.writeDepth++; + else + rwc.counters.writeDepth += 2; + mDataLock.unlock(); + + if (error) + shdfnd::atomicIncrement(&mConcurrentErrorCount); + + return !error; +} + +void ApexRWLockable::stopWrite(bool allowReentry) +{ + shdfnd::atomicDecrement(&mConcurrentWriteCount); + + // decrement depth of writes for this thread + mDataLock.lock(); + nvidia::ThreadImpl::Id id = nvidia::Thread::getId(); + + // see comment in startWrite() + if (allowReentry) + mData[id].counters.writeDepth--; + else + mData[id].counters.writeDepth -= 2; + + mDataLock.unlock(); +} + +nvidia::Thread::Id ApexRWLockable::getCurrentWriter() const +{ + return mCurrentWriter; +} + +bool ApexRWLockable::startRead() const +{ + shdfnd::atomicIncrement(&mConcurrentReadCount); + + mDataLock.lock(); + nvidia::ThreadImpl::Id id = nvidia::Thread::getId(); + ThreadReadWriteCount& rwc = mData[id]; + rwc.counters.readDepth++; + bool success = (rwc.counters.writeDepth > 0 || mConcurrentWriteCount == 0); + mDataLock.unlock(); + + if (!success) + shdfnd::atomicIncrement(&mConcurrentErrorCount); + + return success; +} + +void ApexRWLockable::stopRead() const +{ + shdfnd::atomicDecrement(&mConcurrentReadCount); + mDataLock.lock(); + nvidia::ThreadImpl::Id id = nvidia::Thread::getId(); + mData[id].counters.readDepth--; + mDataLock.unlock(); +} + +uint32_t ApexRWLockable::getReadWriteErrorCount() const +{ + return static_cast<uint32_t>(mConcurrentErrorCount); +} + +ApexRWLockableScopedDisable::ApexRWLockableScopedDisable(RWLockable* rw) : mLockable(static_cast<ApexRWLockable*>(rw)) +{ + mLockable->setEnabled(false); +} + +ApexRWLockableScopedDisable::~ApexRWLockableScopedDisable() +{ + mLockable->setEnabled(true); +} + +ApexRWLockableScopedDisable::ApexRWLockableScopedDisable(const ApexRWLockableScopedDisable& o) : mLockable(o.mLockable) +{ +} + +ApexRWLockableScopedDisable& ApexRWLockableScopedDisable::operator=(const ApexRWLockableScopedDisable&) +{ + return *this; +} + +} +}
\ No newline at end of file |