LCOV - code coverage report
Current view: top level - src/base - once.h (source / functions) Hit Total Coverage
Test: app.info Lines: 8 8 100.0 %
Date: 2019-04-17 Functions: 3 4 75.0 %

          Line data    Source code
       1             : // Copyright 2012 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             : // emulates google3/base/once.h
       6             : //
       7             : // This header is intended to be included only by v8's internal code. Users
       8             : // should not use this directly.
       9             : //
      10             : // This is basically a portable version of pthread_once().
      11             : //
      12             : // This header declares:
      13             : // * A type called OnceType.
      14             : // * A macro V8_DECLARE_ONCE() which declares a (global) variable of type
      15             : //   OnceType.
      16             : // * A function CallOnce(OnceType* once, void (*init_func)()).
      17             : //   This function, when invoked multiple times given the same OnceType object,
      18             : //   will invoke init_func on the first call only, and will make sure none of
      19             : //   the calls return before that first call to init_func has finished.
      20             : //
      21             : // Additionally, the following features are supported:
      22             : // * A macro V8_ONCE_INIT which is expanded into the expression used to
      23             : //   initialize a OnceType. This is only useful when clients embed a OnceType
      24             : //   into a structure of their own and want to initialize it statically.
      25             : // * The user can provide a parameter which CallOnce() forwards to the
      26             : //   user-provided function when it is called. Usage example:
      27             : //     CallOnce(&my_once, &MyFunctionExpectingIntArgument, 10);
      28             : // * This implementation guarantees that OnceType is a POD (i.e. no static
      29             : //   initializer generated).
      30             : //
      31             : // This implements a way to perform lazy initialization.  It's more efficient
      32             : // than using mutexes as no lock is needed if initialization has already
      33             : // happened.
      34             : //
      35             : // Example usage:
      36             : //   void Init();
      37             : //   V8_DECLARE_ONCE(once_init);
      38             : //
      39             : //   // Calls Init() exactly once.
      40             : //   void InitOnce() {
      41             : //     CallOnce(&once_init, &Init);
      42             : //   }
      43             : //
      44             : // Note that if CallOnce() is called before main() has begun, it must
      45             : // only be called by the thread that will eventually call main() -- that is,
      46             : // the thread that performs dynamic initialization.  In general this is a safe
      47             : // assumption since people don't usually construct threads before main() starts,
      48             : // but it is technically not guaranteed.  Unfortunately, Win32 provides no way
      49             : // whatsoever to statically-initialize its synchronization primitives, so our
      50             : // only choice is to assume that dynamic initialization is single-threaded.
      51             : 
      52             : #ifndef V8_BASE_ONCE_H_
      53             : #define V8_BASE_ONCE_H_
      54             : 
      55             : #include <stddef.h>
      56             : #include <atomic>
      57             : #include <functional>
      58             : 
      59             : #include "src/base/base-export.h"
      60             : 
      61             : namespace v8 {
      62             : namespace base {
      63             : 
      64             : using OnceType = std::atomic<uint8_t>;
      65             : 
      66             : #define V8_ONCE_INIT \
      67             :   { 0 }
      68             : 
      69             : #define V8_DECLARE_ONCE(NAME) ::v8::base::OnceType NAME
      70             : 
      71             : enum : uint8_t {
      72             :   ONCE_STATE_UNINITIALIZED = 0,
      73             :   ONCE_STATE_EXECUTING_FUNCTION = 1,
      74             :   ONCE_STATE_DONE = 2
      75             : };
      76             : 
      77             : using PointerArgFunction = void (*)(void* arg);
      78             : 
      79             : template <typename T>
      80             : struct OneArgFunction {
      81             :   using type = void (*)(T);
      82             : };
      83             : 
      84             : V8_BASE_EXPORT void CallOnceImpl(OnceType* once,
      85             :                                  std::function<void()> init_func);
      86             : 
      87      127844 : inline void CallOnce(OnceType* once, std::function<void()> init_func) {
      88      127844 :   if (once->load(std::memory_order_acquire) != ONCE_STATE_DONE) {
      89      145137 :     CallOnceImpl(once, init_func);
      90             :   }
      91      127843 : }
      92             : 
      93             : template <typename Arg>
      94    83293338 : inline void CallOnce(OnceType* once,
      95             :     typename OneArgFunction<Arg*>::type init_func, Arg* arg) {
      96    83293338 :   if (once->load(std::memory_order_acquire) != ONCE_STATE_DONE) {
      97     1396623 :     CallOnceImpl(once, [=]() { init_func(arg); });
      98             :   }
      99    83293338 : }
     100             : 
     101             : }  // namespace base
     102             : }  // namespace v8
     103             : 
     104             : #endif  // V8_BASE_ONCE_H_

Generated by: LCOV version 1.10