v8  10.1.124 (node 18.2.0)
V8 is Google's open source JavaScript engine
v8-locker.h
Go to the documentation of this file.
1 // Copyright 2021 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 INCLUDE_V8_LOCKER_H_
6 #define INCLUDE_V8_LOCKER_H_
7 
8 #include "v8config.h" // NOLINT(build/include_directory)
9 
10 namespace v8 {
11 
12 namespace internal {
13 class Isolate;
14 } // namespace internal
15 
16 class Isolate;
17 
18 /**
19  * Multiple threads in V8 are allowed, but only one thread at a time is allowed
20  * to use any given V8 isolate, see the comments in the Isolate class. The
21  * definition of 'using a V8 isolate' includes accessing handles or holding onto
22  * object pointers obtained from V8 handles while in the particular V8 isolate.
23  * It is up to the user of V8 to ensure, perhaps with locking, that this
24  * constraint is not violated. In addition to any other synchronization
25  * mechanism that may be used, the v8::Locker and v8::Unlocker classes must be
26  * used to signal thread switches to V8.
27  *
28  * v8::Locker is a scoped lock object. While it's active, i.e. between its
29  * construction and destruction, the current thread is allowed to use the locked
30  * isolate. V8 guarantees that an isolate can be locked by at most one thread at
31  * any time. In other words, the scope of a v8::Locker is a critical section.
32  *
33  * Sample usage:
34  * \code
35  * ...
36  * {
37  * v8::Locker locker(isolate);
38  * v8::Isolate::Scope isolate_scope(isolate);
39  * ...
40  * // Code using V8 and isolate goes here.
41  * ...
42  * } // Destructor called here
43  * \endcode
44  *
45  * If you wish to stop using V8 in a thread A you can do this either by
46  * destroying the v8::Locker object as above or by constructing a v8::Unlocker
47  * object:
48  *
49  * \code
50  * {
51  * isolate->Exit();
52  * v8::Unlocker unlocker(isolate);
53  * ...
54  * // Code not using V8 goes here while V8 can run in another thread.
55  * ...
56  * } // Destructor called here.
57  * isolate->Enter();
58  * \endcode
59  *
60  * The Unlocker object is intended for use in a long-running callback from V8,
61  * where you want to release the V8 lock for other threads to use.
62  *
63  * The v8::Locker is a recursive lock, i.e. you can lock more than once in a
64  * given thread. This can be useful if you have code that can be called either
65  * from code that holds the lock or from code that does not. The Unlocker is
66  * not recursive so you can not have several Unlockers on the stack at once, and
67  * you cannot use an Unlocker in a thread that is not inside a Locker's scope.
68  *
69  * An unlocker will unlock several lockers if it has to and reinstate the
70  * correct depth of locking on its destruction, e.g.:
71  *
72  * \code
73  * // V8 not locked.
74  * {
75  * v8::Locker locker(isolate);
76  * Isolate::Scope isolate_scope(isolate);
77  * // V8 locked.
78  * {
79  * v8::Locker another_locker(isolate);
80  * // V8 still locked (2 levels).
81  * {
82  * isolate->Exit();
83  * v8::Unlocker unlocker(isolate);
84  * // V8 not locked.
85  * }
86  * isolate->Enter();
87  * // V8 locked again (2 levels).
88  * }
89  * // V8 still locked (1 level).
90  * }
91  * // V8 Now no longer locked.
92  * \endcode
93  */
95  public:
96  /**
97  * Initialize Unlocker for a given Isolate.
98  */
99  V8_INLINE explicit Unlocker(Isolate* isolate) { Initialize(isolate); }
100 
102 
103  private:
104  void Initialize(Isolate* isolate);
105 
106  internal::Isolate* isolate_;
107 };
108 
110  public:
111  /**
112  * Initialize Locker for a given Isolate.
113  */
114  V8_INLINE explicit Locker(Isolate* isolate) { Initialize(isolate); }
115 
116  ~Locker();
117 
118  /**
119  * Returns whether or not the locker for a given isolate, is locked by the
120  * current thread.
121  */
122  static bool IsLocked(Isolate* isolate);
123 
124  /**
125  * Returns whether any v8::Locker has ever been used in this process.
126  * TODO(cbruni, chromium:1240851): Fix locking checks on a per-thread basis.
127  * The current implementation is quite confusing and leads to unexpected
128  * results if anybody uses v8::Locker in the current process.
129  */
130  V8_DEPRECATE_SOON("This method will be removed.")
131  static bool WasEverUsed();
132  V8_DEPRECATED("Use WasEverUsed instead")
133  static bool IsActive();
134 
135  // Disallow copying and assigning.
136  Locker(const Locker&) = delete;
137  void operator=(const Locker&) = delete;
138 
139  private:
140  void Initialize(Isolate* isolate);
141 
142  bool has_lock_;
143  bool top_level_;
144  internal::Isolate* isolate_;
145 };
146 
147 } // namespace v8
148 
149 #endif // INCLUDE_V8_LOCKER_H_