Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ReadWriteLock upgradeToWrite fix for simultaneous upgrades. #134

Merged
merged 1 commit into from
Nov 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions quantum/impl/quantum_read_write_mutex_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ void ReadWriteMutex::upgradeToWrite()
inline
void ReadWriteMutex::upgradeToWrite(ICoroSync::Ptr sync)
{
while (!tryUpgradeToWrite())
bool pendingUpgrade = false;
while (!tryUpgradeToWriteImpl(&pendingUpgrade))
{
yield(sync);
}
Expand All @@ -100,7 +101,19 @@ void ReadWriteMutex::upgradeToWrite(ICoroSync::Ptr sync)
inline
bool ReadWriteMutex::tryUpgradeToWrite()
{
bool rc = _spinlock.tryUpgradeToWrite();
return tryUpgradeToWriteImpl(nullptr);
}

inline
bool ReadWriteMutex::tryUpgradeToWriteImpl(bool* pendingUpgrade)
{
bool rc;
if (pendingUpgrade) {
rc = _spinlock.tryUpgradeToWrite(*pendingUpgrade);
}
else {
rc = _spinlock.tryUpgradeToWrite();
}
if (rc)
{
_taskId = local::taskId();
Expand All @@ -119,7 +132,6 @@ void ReadWriteMutex::unlockWrite()
{
assert(_taskId == local::taskId());
_taskId = TaskId{}; //reset the task id

_spinlock.unlockWrite();
}

Expand Down
18 changes: 12 additions & 6 deletions quantum/impl/quantum_read_write_spinlock_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,25 +71,25 @@ namespace quantum {
inline
void ReadWriteSpinLock::lockRead()
{
SpinLockUtil::lockRead(_count);
SpinLockUtil::lockRead(_count, LockTraits::Attempt::Unlimited);
}

inline
void ReadWriteSpinLock::lockWrite()
{
SpinLockUtil::lockWrite(_count);
SpinLockUtil::lockWrite(_count, LockTraits::Attempt::Unlimited);
}

inline
bool ReadWriteSpinLock::tryLockRead()
{
return SpinLockUtil::lockRead(_count, true);
return SpinLockUtil::lockRead(_count, LockTraits::Attempt::Once);
}

inline
bool ReadWriteSpinLock::tryLockWrite()
{
return SpinLockUtil::lockWrite(_count, true);
return SpinLockUtil::lockWrite(_count, LockTraits::Attempt::Once);
}

inline
Expand All @@ -107,13 +107,19 @@ void ReadWriteSpinLock::unlockWrite()
inline
void ReadWriteSpinLock::upgradeToWrite()
{
SpinLockUtil::upgradeToWrite(_count);
SpinLockUtil::upgradeToWrite(_count, LockTraits::Attempt::Unlimited);
}

inline
bool ReadWriteSpinLock::tryUpgradeToWrite()
{
return SpinLockUtil::upgradeToWrite(_count, true);
return SpinLockUtil::upgradeToWrite(_count, LockTraits::Attempt::Once);
}

inline
bool ReadWriteSpinLock::tryUpgradeToWrite(bool& pendingUpgrade)
{
return SpinLockUtil::upgradeToWrite(_count, pendingUpgrade, LockTraits::Attempt::Reentrant);
}

inline
Expand Down
4 changes: 2 additions & 2 deletions quantum/impl/quantum_spinlock_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ namespace quantum {
inline
void SpinLock::lock()
{
SpinLockUtil::lockWrite(_flag);
SpinLockUtil::lockWrite(_flag, LockTraits::Attempt::Unlimited);
}

inline
bool SpinLock::tryLock()
{
return SpinLockUtil::lockWrite(_flag, true);
return SpinLockUtil::lockWrite(_flag, LockTraits::Attempt::Once);
}

inline
Expand Down
2 changes: 2 additions & 0 deletions quantum/quantum_read_write_mutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ class ReadWriteMutex
};

private:
bool tryUpgradeToWriteImpl(bool* pendingUpgrade);

// Members
mutable ReadWriteSpinLock _spinlock;
mutable TaskId _taskId;
Expand Down
3 changes: 3 additions & 0 deletions quantum/quantum_read_write_spinlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,11 @@ class ReadWriteSpinLock
void upgradeToWrite();

/// @brief Attempts to upgrade a reader lock to a writer lock. This operation never blocks.
/// @param pendingUpdate Use this overload when calling this function in a loop.
/// PendingUpdate must be initialized to 'false'.
/// @return True if the lock operation succeeded, false otherwise.
bool tryUpgradeToWrite();
bool tryUpgradeToWrite(bool& pendingUpdate);

/// @bried Determines if this object is either read or write locked.
/// @return True if locked, false otherwise.
Expand Down
5 changes: 5 additions & 0 deletions quantum/quantum_spinlock_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ struct SpinLockTraits {
//==============================================================================
struct LockTraits
{
enum class Attempt : uint8_t {
Once, ///> Try to obtain lock once and return success of failure
Unlimited, ///> Try until lock is obtained
Reentrant ///> Try continuously but return on each iteration w/o blocking
};
using TryToLock = std::try_to_lock_t;
using AdoptLock = std::adopt_lock_t;
using DeferLock = std::defer_lock_t;
Expand Down
8 changes: 2 additions & 6 deletions quantum/util/impl/quantum_sequencer_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -373,12 +373,8 @@ Sequencer<SequenceKey, Hash, KeyEqual, Allocator>::singleSequenceKeyTaskSchedule
FUNC&& func,
ARGS&&... args)
{
// find the dependent
typename ContextMap::iterator contextIt = sequencer._contexts.find(sequenceKey);
if (contextIt == sequencer._contexts.end())
{
contextIt = sequencer._contexts.emplace(sequenceKey, SequenceKeyData()).first;
}
// find the dependent or create a new element
typename ContextMap::iterator contextIt = sequencer._contexts.emplace(sequenceKey, SequenceKeyData()).first;
// update stats
contextIt->second._stats->incrementPostedTaskCount();
contextIt->second._stats->incrementPendingTaskCount();
Expand Down
Loading