mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 20:51:19 +00:00
[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:
parent
af4757dd0b
commit
f3740ced59
|
@ -56,8 +56,7 @@ SafepointMutexLocker::SafepointMutexLocker(ThreadState* thread, Mutex* mutex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SafepointMonitorLocker::SafepointMonitorLocker(Monitor* monitor)
|
void SafepointMonitorLocker::AcquireLock() {
|
||||||
: monitor_(monitor) {
|
|
||||||
ASSERT(monitor_ != NULL);
|
ASSERT(monitor_ != NULL);
|
||||||
if (!monitor_->TryEnter()) {
|
if (!monitor_->TryEnter()) {
|
||||||
// We did not get the lock and could potentially block, so transition
|
// 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) {
|
Monitor::WaitResult SafepointMonitorLocker::Wait(int64_t millis) {
|
||||||
Thread* thread = Thread::Current();
|
Thread* thread = Thread::Current();
|
||||||
if (thread != NULL) {
|
if (thread != NULL) {
|
||||||
|
|
|
@ -259,19 +259,38 @@ class SafepointMutexLocker : public StackResource {
|
||||||
*/
|
*/
|
||||||
class SafepointMonitorLocker : public ValueObject {
|
class SafepointMonitorLocker : public ValueObject {
|
||||||
public:
|
public:
|
||||||
explicit SafepointMonitorLocker(Monitor* monitor);
|
explicit SafepointMonitorLocker(Monitor* monitor) : monitor_(monitor) {
|
||||||
virtual ~SafepointMonitorLocker() { monitor_->Exit(); }
|
AcquireLock();
|
||||||
|
}
|
||||||
|
virtual ~SafepointMonitorLocker() { ReleaseLock(); }
|
||||||
|
|
||||||
Monitor::WaitResult Wait(int64_t millis = Monitor::kNoTimeout);
|
Monitor::WaitResult Wait(int64_t millis = Monitor::kNoTimeout);
|
||||||
|
|
||||||
void NotifyAll() { monitor_->NotifyAll(); }
|
void NotifyAll() { monitor_->NotifyAll(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class SafepointMonitorUnlockScope;
|
||||||
|
|
||||||
|
void AcquireLock();
|
||||||
|
void ReleaseLock();
|
||||||
|
|
||||||
Monitor* const monitor_;
|
Monitor* const monitor_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(SafepointMonitorLocker);
|
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 {
|
class RwLock {
|
||||||
public:
|
public:
|
||||||
RwLock() {}
|
RwLock() {}
|
||||||
|
|
|
@ -1102,4 +1102,23 @@ ISOLATE_UNIT_TEST_CASE(SafepointRwLockExclusiveNestedWriter_Regress44000) {
|
||||||
EXPECT(state.elapsed_us > 2 * 500 * 1000);
|
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
|
} // namespace dart
|
||||||
|
|
Loading…
Reference in a new issue