LCOV - code coverage report
Current view: top level - src/torque - contextual.h (source / functions) Hit Total Coverage
Test: app.info Lines: 8 8 100.0 %
Date: 2019-04-17 Functions: 18 19 94.7 %

          Line data    Source code
       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>
      28             : class ContextualVariable {
      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      307346 :     explicit Scope(Args&&... args)
      41      317088 :         : current_(std::forward<Args>(args)...), previous_(Top()) {
      42      314190 :       Top() = &current_;
      43      307346 :     }
      44           6 :     ~Scope() {
      45             :       // Ensure stack discipline.
      46             :       DCHECK_EQ(&current_, Top());
      47      314190 :       Top() = previous_;
      48      314190 :     }
      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     4615007 :     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_

Generated by: LCOV version 1.10