v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
contextual.h
Go to the documentation of this file.
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_BASE_CONTEXTUAL_H_
6#define V8_BASE_CONTEXTUAL_H_
7
8#include <type_traits>
9
11#include "src/base/macros.h"
13
14namespace v8::base {
15
16// {ContextualVariable} provides a clean alternative to a global variable.
17// The contextual variable is mutable, and supports managing the value of
18// a variable in a well-nested fashion via the {Scope} class.
19// {ContextualVariable} only stores a pointer to the current value, which
20// is stored in a {Scope} object. The most recent value can be retrieved
21// via Get(). Because only {Scope} has actual storage, there must be at
22// least one active {Scope} (i.e. in a surrounding C++ scope), whenever Get()
23// is called.
24// Note that contextual variables must only be used from the same thread,
25// i.e. {Scope} and Get() have to be in the same thread.
26template <class Derived, class VarType>
28 public:
29 using VarT = VarType;
30
31 // A {Scope} contains a new object of type {VarType} and gives
32 // ContextualVariable::Get() access to it. Upon destruction, the contextual
33 // variable is restored to the state before the {Scope} was created. Scopes
34 // have to follow a stack discipline: A {Scope} has to be destructed before
35 // any older scope is destructed.
37 public:
38 template <class... Args>
39 explicit Scope(Args&&... args)
40 : value_(std::forward<Args>(args)...), previous_(Top()) {
41 Top() = this;
42 }
44 // Ensure stack discipline.
45 DCHECK_EQ(this, Top());
46 Top() = previous_;
47 }
48
49 Scope(const Scope&) = delete;
50 Scope& operator=(const Scope&) = delete;
51
52 VarType& Value() { return value_; }
53
54 private:
55 VarType value_;
57
58 static_assert(std::is_base_of<ContextualVariable, Derived>::value,
59 "Curiously Recurring Template Pattern");
60
62 };
63
64 static VarType& Get() {
65 DCHECK(HasScope());
66 return Top()->Value();
67 }
68
69 static bool HasScope() { return Top() != nullptr; }
70
71 private:
72 inline static thread_local Scope* top_ = nullptr;
73
74#if defined(USING_V8_SHARED)
75 // Hide the access to `top_` from other DLLs/libraries, since access to
76 // thread_local variables from other DLLs/libraries does not work correctly.
77 static Scope*& Top() { return ExportedTop(); }
78#else
79 static Scope*& Top() { return top_; }
80#endif
81 // Same as `Top()`, but non-inline and exported to DLLs/libraries.
82 // If there is a linking error for `ExportedTop()`, then the contextual
83 // variable probably needs to be exported using EXPORT_CONTEXTUAL_VARIABLE.
84 static Scope*& ExportedTop();
85};
86
87// Usage: DECLARE_CONTEXTUAL_VARIABLE(VarName, VarType)
88#define DECLARE_CONTEXTUAL_VARIABLE(VarName, ...) \
89 struct VarName : ::v8::base::ContextualVariable<VarName, __VA_ARGS__> {}
90
91// Contextual variables that are accessed in tests need to be
92// exported. For this, place the following macro in the global namespace inside
93// of a .cc file.
94#define EXPORT_CONTEXTUAL_VARIABLE(VarName) \
95 namespace v8::base { \
96 template <> \
97 V8_EXPORT_PRIVATE typename VarName::Scope*& \
98 ContextualVariable<VarName, typename VarName::VarT>::ExportedTop() { \
99 return top_; \
100 } \
101 }
102
103// By inheriting from {ContextualClass} a class can become a contextual variable
104// of itself, which is very similar to a singleton.
105template <class T>
107
108// {ContextualVariableWithDefault} is similar to a {ContextualVariable},
109// with the difference that a default value is used if there is no active
110// {Scope} object.
111template <class Derived, class VarType, auto... default_args>
113 : public ContextualVariable<Derived, VarType> {
114 public:
115 static VarType& Get() {
116 return Base::HasScope() ? Base::Get() : default_value_;
117 }
118
119 private:
121 inline static thread_local VarType default_value_{default_args...};
122};
123
124// Usage: DECLARE_CONTEXTUAL_VARIABLE_WITH_DEFAULT(VarName, VarType, Args...)
125#define DECLARE_CONTEXTUAL_VARIABLE_WITH_DEFAULT(VarName, ...) \
126 struct VarName \
127 : ::v8::base::ContextualVariableWithDefault<VarName, __VA_ARGS__> {}
128
129} // namespace v8::base
130
131#endif // V8_BASE_CONTEXTUAL_H_
Scope & operator=(const Scope &)=delete
static VarType & Get()
Definition contextual.h:64
static Scope *& Top()
Definition contextual.h:79
static Scope *& ExportedTop()
Register const value_
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
STL namespace.
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DISALLOW_NEW_AND_DELETE()
Definition macros.h:155
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define V8_NODISCARD
Definition v8config.h:693