xref: /third_party/node/deps/v8/src/heap/parked-scope.h (revision 1cb0ef41)
1// Copyright 2020 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_HEAP_PARKED_SCOPE_H_
6#define V8_HEAP_PARKED_SCOPE_H_
7
8#include "src/base/platform/mutex.h"
9#include "src/execution/local-isolate.h"
10#include "src/heap/local-heap.h"
11
12namespace v8 {
13namespace internal {
14
15// Scope that explicitly parks a thread, prohibiting access to the heap and the
16// creation of handles.
17class V8_NODISCARD ParkedScope {
18 public:
19  explicit ParkedScope(LocalIsolate* local_isolate)
20      : ParkedScope(local_isolate->heap()) {}
21  explicit ParkedScope(LocalHeap* local_heap) : local_heap_(local_heap) {
22    local_heap_->Park();
23  }
24
25  ~ParkedScope() { local_heap_->Unpark(); }
26
27 private:
28  LocalHeap* const local_heap_;
29};
30
31// Scope that explicitly unparks a thread, allowing access to the heap and the
32// creation of handles.
33class V8_NODISCARD UnparkedScope {
34 public:
35  explicit UnparkedScope(LocalIsolate* local_isolate)
36      : UnparkedScope(local_isolate->heap()) {}
37  explicit UnparkedScope(LocalHeap* local_heap) : local_heap_(local_heap) {
38    local_heap_->Unpark();
39  }
40
41  ~UnparkedScope() { local_heap_->Park(); }
42
43 private:
44  LocalHeap* const local_heap_;
45};
46
47// Scope that automatically parks the thread while blocking on the given
48// base::Mutex.
49class V8_NODISCARD ParkedMutexGuard {
50 public:
51  explicit ParkedMutexGuard(LocalIsolate* local_isolate, base::Mutex* mutex)
52      : ParkedMutexGuard(local_isolate->heap(), mutex) {}
53  explicit ParkedMutexGuard(LocalHeap* local_heap, base::Mutex* mutex)
54      : mutex_(mutex) {
55    DCHECK(AllowGarbageCollection::IsAllowed());
56    if (!mutex_->TryLock()) {
57      ParkedScope scope(local_heap);
58      mutex_->Lock();
59    }
60  }
61
62  ParkedMutexGuard(const ParkedMutexGuard&) = delete;
63  ParkedMutexGuard& operator=(const ParkedMutexGuard&) = delete;
64
65  ~ParkedMutexGuard() { mutex_->Unlock(); }
66
67 private:
68  base::Mutex* mutex_;
69};
70
71template <base::MutexSharedType kIsShared,
72          base::NullBehavior Behavior = base::NullBehavior::kRequireNotNull>
73class V8_NODISCARD ParkedSharedMutexGuardIf final {
74 public:
75  ParkedSharedMutexGuardIf(LocalIsolate* local_isolate,
76                           base::SharedMutex* mutex, bool enable_mutex)
77      : ParkedSharedMutexGuardIf(local_isolate->heap(), mutex, enable_mutex) {}
78  ParkedSharedMutexGuardIf(LocalHeap* local_heap, base::SharedMutex* mutex,
79                           bool enable_mutex) {
80    DCHECK(AllowGarbageCollection::IsAllowed());
81    DCHECK_IMPLIES(Behavior == base::NullBehavior::kRequireNotNull,
82                   mutex != nullptr);
83    if (!enable_mutex) return;
84    mutex_ = mutex;
85
86    if (kIsShared) {
87      if (!mutex_->TryLockShared()) {
88        ParkedScope scope(local_heap);
89        mutex_->LockShared();
90      }
91    } else {
92      if (!mutex_->TryLockExclusive()) {
93        ParkedScope scope(local_heap);
94        mutex_->LockExclusive();
95      }
96    }
97  }
98  ParkedSharedMutexGuardIf(const ParkedSharedMutexGuardIf&) = delete;
99  ParkedSharedMutexGuardIf& operator=(const ParkedSharedMutexGuardIf&) = delete;
100
101  ~ParkedSharedMutexGuardIf() {
102    if (!mutex_) return;
103
104    if (kIsShared) {
105      mutex_->UnlockShared();
106    } else {
107      mutex_->UnlockExclusive();
108    }
109  }
110
111 private:
112  base::SharedMutex* mutex_ = nullptr;
113};
114
115}  // namespace internal
116}  // namespace v8
117
118#endif  // V8_HEAP_PARKED_SCOPE_H_
119