Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit f3740ce

Browse files
mkustermanncommit-bot@chromium.org
authored andcommitted
[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 dart-lang/sdk#36097 TEST=Refactoring of existing code. Change-Id: I004a04e54dcdaea009bfbef25d2a946a307e41c6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/187001 Reviewed-by: Alexander Aprelev <[email protected]> Reviewed-by: Ryan Macnak <[email protected]> Commit-Queue: Martin Kustermann <[email protected]>
1 parent af4757d commit f3740ce

File tree

3 files changed

+45
-4
lines changed

3 files changed

+45
-4
lines changed

runtime/vm/lockers.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ SafepointMutexLocker::SafepointMutexLocker(ThreadState* thread, Mutex* mutex)
5656
}
5757
}
5858

59-
SafepointMonitorLocker::SafepointMonitorLocker(Monitor* monitor)
60-
: monitor_(monitor) {
59+
void SafepointMonitorLocker::AcquireLock() {
6160
ASSERT(monitor_ != NULL);
6261
if (!monitor_->TryEnter()) {
6362
// We did not get the lock and could potentially block, so transition
@@ -72,6 +71,10 @@ SafepointMonitorLocker::SafepointMonitorLocker(Monitor* monitor)
7271
}
7372
}
7473

74+
void SafepointMonitorLocker::ReleaseLock() {
75+
monitor_->Exit();
76+
}
77+
7578
Monitor::WaitResult SafepointMonitorLocker::Wait(int64_t millis) {
7679
Thread* thread = Thread::Current();
7780
if (thread != NULL) {

runtime/vm/lockers.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,19 +259,38 @@ class SafepointMutexLocker : public StackResource {
259259
*/
260260
class SafepointMonitorLocker : public ValueObject {
261261
public:
262-
explicit SafepointMonitorLocker(Monitor* monitor);
263-
virtual ~SafepointMonitorLocker() { monitor_->Exit(); }
262+
explicit SafepointMonitorLocker(Monitor* monitor) : monitor_(monitor) {
263+
AcquireLock();
264+
}
265+
virtual ~SafepointMonitorLocker() { ReleaseLock(); }
264266

265267
Monitor::WaitResult Wait(int64_t millis = Monitor::kNoTimeout);
266268

267269
void NotifyAll() { monitor_->NotifyAll(); }
268270

269271
private:
272+
friend class SafepointMonitorUnlockScope;
273+
274+
void AcquireLock();
275+
void ReleaseLock();
276+
270277
Monitor* const monitor_;
271278

272279
DISALLOW_COPY_AND_ASSIGN(SafepointMonitorLocker);
273280
};
274281

282+
class SafepointMonitorUnlockScope : public ValueObject {
283+
public:
284+
explicit SafepointMonitorUnlockScope(SafepointMonitorLocker* locker)
285+
: locker_(locker) {
286+
locker_->ReleaseLock();
287+
}
288+
~SafepointMonitorUnlockScope() { locker_->AcquireLock(); }
289+
290+
private:
291+
SafepointMonitorLocker* locker_;
292+
};
293+
275294
class RwLock {
276295
public:
277296
RwLock() {}

runtime/vm/thread_test.cc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,4 +1102,23 @@ ISOLATE_UNIT_TEST_CASE(SafepointRwLockExclusiveNestedWriter_Regress44000) {
11021102
EXPECT(state.elapsed_us > 2 * 500 * 1000);
11031103
}
11041104

1105+
ISOLATE_UNIT_TEST_CASE(SafepointMonitorUnlockScope) {
1106+
// This test uses ASSERT instead of EXPECT because IsOwnedByCurrentThread is
1107+
// only available in debug mode. Since our vm/cc tests run in DEBUG mode that
1108+
// is sufficent for this test.
1109+
Monitor monitor;
1110+
{
1111+
SafepointMonitorLocker ml(&monitor);
1112+
ASSERT(monitor.IsOwnedByCurrentThread());
1113+
{
1114+
SafepointMonitorUnlockScope ml_unlocker(&ml);
1115+
ASSERT(!monitor.IsOwnedByCurrentThread());
1116+
{
1117+
SafepointMonitorLocker inner_ml(&monitor);
1118+
ASSERT(monitor.IsOwnedByCurrentThread());
1119+
}
1120+
}
1121+
}
1122+
}
1123+
11051124
} // namespace dart

0 commit comments

Comments
 (0)