V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
contextual.h
1 // Copyright 2018 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_TORQUE_CONTEXTUAL_H_
6 #define V8_TORQUE_CONTEXTUAL_H_
7 
8 #include <type_traits>
9 
10 #include "src/base/macros.h"
11 #include "src/base/platform/platform.h"
12 
13 namespace v8 {
14 namespace internal {
15 namespace torque {
16 
17 // {ContextualVariable} provides a clean alternative to a global variable.
18 // The contextual variable is mutable, and supports managing the value of
19 // a variable in a well-nested fashion via the {Scope} class.
20 // {ContextualVariable} only stores a pointer to the current value, which
21 // is stored in a {Scope} object. The most recent value can be retrieved
22 // via Get(). Because only {Scope} has actual storage, there must be at
23 // least one active {Scope} (i.e. in a surrounding C++ scope), whenever Get()
24 // is called.
25 // Note that contextual variables must only be used from the same thread,
26 // i.e. {Scope} and Get() have to be in the same thread.
27 template <class Derived, class VarType>
29  public:
30  using VariableType = VarType;
31 
32  // A {Scope} contains a new object of type {VarType} and gives
33  // ContextualVariable::Get() access to it. Upon destruction, the contextual
34  // variable is restored to the state before the {Scope} was created. Scopes
35  // have to follow a stack discipline: A {Scope} has to be destructed before
36  // any older scope is destructed.
37  class Scope {
38  public:
39  template <class... Args>
40  explicit Scope(Args&&... args)
41  : current_(std::forward<Args>(args)...), previous_(Top()) {
42  Top() = &current_;
43  }
44  ~Scope() {
45  // Ensure stack discipline.
46  DCHECK_EQ(&current_, Top());
47  Top() = previous_;
48  }
49 
50  private:
51  VarType current_;
52  VarType* previous_;
53 
54  static_assert(std::is_base_of<ContextualVariable, Derived>::value,
55  "Curiously Recurring Template Pattern");
56 
57  DISALLOW_NEW_AND_DELETE();
58  DISALLOW_COPY_AND_ASSIGN(Scope);
59  };
60 
61  // Access the most recent active {Scope}. There has to be an active {Scope}
62  // for this contextual variable.
63  static VarType& Get() {
64  DCHECK_NOT_NULL(Top());
65  return *Top();
66  }
67 
68  private:
69  V8_EXPORT_PRIVATE static VarType*& Top();
70 };
71 
72 // Usage: DECLARE_CONTEXTUAL_VARIABLE(VarName, VarType)
73 #define DECLARE_CONTEXTUAL_VARIABLE(VarName, ...) \
74  struct VarName \
75  : v8::internal::torque::ContextualVariable<VarName, __VA_ARGS__> {};
76 
77 #define DEFINE_CONTEXTUAL_VARIABLE(VarName) \
78  template <> \
79  V8_EXPORT_PRIVATE VarName::VariableType*& \
80  ContextualVariable<VarName, VarName::VariableType>::Top() { \
81  static thread_local VarName::VariableType* top = nullptr; \
82  return top; \
83  }
84 
85 // By inheriting from {ContextualClass} a class can become a contextual variable
86 // of itself, which is very similar to a singleton.
87 template <class T>
88 using ContextualClass = ContextualVariable<T, T>;
89 
90 } // namespace torque
91 } // namespace internal
92 } // namespace v8
93 
94 #endif // V8_TORQUE_CONTEXTUAL_H_
Definition: libplatform.h:13