[vm/concurrency] Add SafepointMonitorUnlockScope to allow scoped unlocking of a monitor
In order to simplify code that needs to temporarily give up a monitor lock, this CL adds a scoped object that releases the monitor on construction and re-acquires it on destruction. Issue https://github.com/dart-lang/sdk/issues/36097 TEST=Refactoring of existing code. Change-Id: I004a04e54dcdaea009bfbef25d2a946a307e41c6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/187001 Reviewed-by: Alexander Aprelev <aam@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com> Commit-Queue: Martin Kustermann <kustermann@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
af4757dd0b
commit
f3740ced59
@@ -56,8 +56,7 @@ SafepointMutexLocker::SafepointMutexLocker(ThreadState* thread, Mutex* mutex)
|
||||
}
|
||||
}
|
||||
|
||||
SafepointMonitorLocker::SafepointMonitorLocker(Monitor* monitor)
|
||||
: monitor_(monitor) {
|
||||
void SafepointMonitorLocker::AcquireLock() {
|
||||
ASSERT(monitor_ != NULL);
|
||||
if (!monitor_->TryEnter()) {
|
||||
// We did not get the lock and could potentially block, so transition
|
||||
@@ -72,6 +71,10 @@ SafepointMonitorLocker::SafepointMonitorLocker(Monitor* monitor)
|
||||
}
|
||||
}
|
||||
|
||||
void SafepointMonitorLocker::ReleaseLock() {
|
||||
monitor_->Exit();
|
||||
}
|
||||
|
||||
Monitor::WaitResult SafepointMonitorLocker::Wait(int64_t millis) {
|
||||
Thread* thread = Thread::Current();
|
||||
if (thread != NULL) {
|
||||
|
||||
+21
-2
@@ -259,19 +259,38 @@ class SafepointMutexLocker : public StackResource {
|
||||
*/
|
||||
class SafepointMonitorLocker : public ValueObject {
|
||||
public:
|
||||
explicit SafepointMonitorLocker(Monitor* monitor);
|
||||
virtual ~SafepointMonitorLocker() { monitor_->Exit(); }
|
||||
explicit SafepointMonitorLocker(Monitor* monitor) : monitor_(monitor) {
|
||||
AcquireLock();
|
||||
}
|
||||
virtual ~SafepointMonitorLocker() { ReleaseLock(); }
|
||||
|
||||
Monitor::WaitResult Wait(int64_t millis = Monitor::kNoTimeout);
|
||||
|
||||
void NotifyAll() { monitor_->NotifyAll(); }
|
||||
|
||||
private:
|
||||
friend class SafepointMonitorUnlockScope;
|
||||
|
||||
void AcquireLock();
|
||||
void ReleaseLock();
|
||||
|
||||
Monitor* const monitor_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SafepointMonitorLocker);
|
||||
};
|
||||
|
||||
class SafepointMonitorUnlockScope : public ValueObject {
|
||||
public:
|
||||
explicit SafepointMonitorUnlockScope(SafepointMonitorLocker* locker)
|
||||
: locker_(locker) {
|
||||
locker_->ReleaseLock();
|
||||
}
|
||||
~SafepointMonitorUnlockScope() { locker_->AcquireLock(); }
|
||||
|
||||
private:
|
||||
SafepointMonitorLocker* locker_;
|
||||
};
|
||||
|
||||
class RwLock {
|
||||
public:
|
||||
RwLock() {}
|
||||
|
||||
@@ -1102,4 +1102,23 @@ ISOLATE_UNIT_TEST_CASE(SafepointRwLockExclusiveNestedWriter_Regress44000) {
|
||||
EXPECT(state.elapsed_us > 2 * 500 * 1000);
|
||||
}
|
||||
|
||||
ISOLATE_UNIT_TEST_CASE(SafepointMonitorUnlockScope) {
|
||||
// This test uses ASSERT instead of EXPECT because IsOwnedByCurrentThread is
|
||||
// only available in debug mode. Since our vm/cc tests run in DEBUG mode that
|
||||
// is sufficent for this test.
|
||||
Monitor monitor;
|
||||
{
|
||||
SafepointMonitorLocker ml(&monitor);
|
||||
ASSERT(monitor.IsOwnedByCurrentThread());
|
||||
{
|
||||
SafepointMonitorUnlockScope ml_unlocker(&ml);
|
||||
ASSERT(!monitor.IsOwnedByCurrentThread());
|
||||
{
|
||||
SafepointMonitorLocker inner_ml(&monitor);
|
||||
ASSERT(monitor.IsOwnedByCurrentThread());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
|
||||
Reference in New Issue
Block a user