LCOV - code coverage report
Current view: top level - src/base - atomic-utils.h (source / functions) Hit Total Coverage
Test: app.info Lines: 21 21 100.0 %
Date: 2019-04-19 Functions: 25 26 96.2 %

          Line data    Source code
       1             : // Copyright 2015 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_ATOMIC_UTILS_H_
       6             : #define V8_BASE_ATOMIC_UTILS_H_
       7             : 
       8             : #include <limits.h>
       9             : #include <type_traits>
      10             : 
      11             : #include "src/base/atomicops.h"
      12             : #include "src/base/macros.h"
      13             : 
      14             : namespace v8 {
      15             : namespace base {
      16             : 
      17             : // Deprecated. Use std::atomic<T> for new code.
      18             : // Flag using T atomically. Also accepts void* as T.
      19             : template <typename T>
      20             : class AtomicValue {
      21             :  public:
      22   180257301 :   AtomicValue() : value_(0) {}
      23             : 
      24             :   explicit AtomicValue(T initial)
      25     1890278 :       : value_(cast_helper<T>::to_storage_type(initial)) {}
      26             : 
      27             :   V8_INLINE T Value() const {
      28    12471061 :     return cast_helper<T>::to_return_type(base::Acquire_Load(&value_));
      29             :   }
      30             : 
      31             :   V8_INLINE void SetValue(T new_value) {
      32     1963351 :     base::Release_Store(&value_, cast_helper<T>::to_storage_type(new_value));
      33             :   }
      34             : 
      35             :  private:
      36             :   STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
      37             : 
      38             :   template <typename S>
      39             :   struct cast_helper {
      40           2 :     static base::AtomicWord to_storage_type(S value) {
      41           2 :       return static_cast<base::AtomicWord>(value);
      42             :     }
      43     1282660 :     static S to_return_type(base::AtomicWord value) {
      44     1282701 :       return static_cast<S>(value);
      45             :     }
      46             :   };
      47             : 
      48             :   template <typename S>
      49             :   struct cast_helper<S*> {
      50      137158 :     static base::AtomicWord to_storage_type(S* value) {
      51      137158 :       return reinterpret_cast<base::AtomicWord>(value);
      52             :     }
      53     4966535 :     static S* to_return_type(base::AtomicWord value) {
      54     4966602 :       return reinterpret_cast<S*>(value);
      55             :     }
      56             :   };
      57             : 
      58             :   base::AtomicWord value_;
      59             : };
      60             : 
      61             : // Provides atomic operations for a values stored at some address.
      62             : template <typename TAtomicStorageType>
      63             : class AsAtomicImpl {
      64             :  public:
      65             :   using AtomicStorageType = TAtomicStorageType;
      66             : 
      67             :   template <typename T>
      68             :   static T Acquire_Load(T* addr) {
      69             :     STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
      70             :     return cast_helper<T>::to_return_type(
      71             :         base::Acquire_Load(to_storage_addr(addr)));
      72             :   }
      73             : 
      74             :   template <typename T>
      75    26293280 :   static T Relaxed_Load(T* addr) {
      76             :     STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
      77             :     return cast_helper<T>::to_return_type(
      78    26293280 :         base::Relaxed_Load(to_storage_addr(addr)));
      79             :   }
      80             : 
      81             :   template <typename T>
      82             :   static void Release_Store(T* addr,
      83             :                             typename std::remove_reference<T>::type new_value) {
      84             :     STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
      85             :     base::Release_Store(to_storage_addr(addr),
      86             :                         cast_helper<T>::to_storage_type(new_value));
      87             :   }
      88             : 
      89             :   template <typename T>
      90             :   static void Relaxed_Store(T* addr,
      91             :                             typename std::remove_reference<T>::type new_value) {
      92             :     STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
      93             :     base::Relaxed_Store(to_storage_addr(addr),
      94             :                         cast_helper<T>::to_storage_type(new_value));
      95             :   }
      96             : 
      97             :   template <typename T>
      98             :   static T Release_CompareAndSwap(
      99             :       T* addr, typename std::remove_reference<T>::type old_value,
     100             :       typename std::remove_reference<T>::type new_value) {
     101             :     STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
     102             :     return cast_helper<T>::to_return_type(base::Release_CompareAndSwap(
     103             :         to_storage_addr(addr), cast_helper<T>::to_storage_type(old_value),
     104             :         cast_helper<T>::to_storage_type(new_value)));
     105             :   }
     106             : 
     107             :   // Atomically sets bits selected by the mask to the given value.
     108             :   // Returns false if the bits are already set as needed.
     109             :   template <typename T>
     110  5626208680 :   static bool SetBits(T* addr, T bits, T mask) {
     111             :     STATIC_ASSERT(sizeof(T) <= sizeof(AtomicStorageType));
     112             :     DCHECK_EQ(bits & ~mask, static_cast<T>(0));
     113             :     T old_value;
     114             :     T new_value;
     115  1323770662 :     do {
     116             :       old_value = Relaxed_Load(addr);
     117  5626398328 :       if ((old_value & mask) == bits) return false;
     118  1323770662 :       new_value = (old_value & ~mask) | bits;
     119             :     } while (Release_CompareAndSwap(addr, old_value, new_value) != old_value);
     120             :     return true;
     121             :   }
     122             : 
     123             :  private:
     124             :   template <typename U>
     125             :   struct cast_helper {
     126             :     static AtomicStorageType to_storage_type(U value) {
     127  1378297761 :       return static_cast<AtomicStorageType>(value);
     128             :     }
     129             :     static U to_return_type(AtomicStorageType value) {
     130  1437899218 :       return static_cast<U>(value);
     131             :     }
     132             :   };
     133             : 
     134             :   template <typename U>
     135             :   struct cast_helper<U*> {
     136             :     static AtomicStorageType to_storage_type(U* value) {
     137             :       return reinterpret_cast<AtomicStorageType>(value);
     138             :     }
     139             :     static U* to_return_type(AtomicStorageType value) {
     140   460741327 :       return reinterpret_cast<U*>(value);
     141             :     }
     142             :   };
     143             : 
     144             :   template <typename T>
     145             :   static AtomicStorageType* to_storage_addr(T* value) {
     146             :     return reinterpret_cast<AtomicStorageType*>(value);
     147             :   }
     148             :   template <typename T>
     149             :   static const AtomicStorageType* to_storage_addr(const T* value) {
     150             :     return reinterpret_cast<const AtomicStorageType*>(value);
     151             :   }
     152             : };
     153             : 
     154             : using AsAtomic8 = AsAtomicImpl<base::Atomic8>;
     155             : using AsAtomic32 = AsAtomicImpl<base::Atomic32>;
     156             : using AsAtomicWord = AsAtomicImpl<base::AtomicWord>;
     157             : 
     158             : // This is similar to AsAtomicWord but it explicitly deletes functionality
     159             : // provided atomic access to bit representation of stored values.
     160             : template <typename TAtomicStorageType>
     161             : class AsAtomicPointerImpl : public AsAtomicImpl<TAtomicStorageType> {
     162             :  public:
     163             :   template <typename T>
     164             :   static bool SetBits(T* addr, T bits, T mask) = delete;
     165             : };
     166             : 
     167             : using AsAtomicPointer = AsAtomicPointerImpl<base::AtomicWord>;
     168             : 
     169             : template <typename T,
     170             :           typename = typename std::enable_if<std::is_unsigned<T>::value>::type>
     171             : inline void CheckedIncrement(std::atomic<T>* number, T amount) {
     172             :   const T old = number->fetch_add(amount);
     173             :   DCHECK_GE(old + amount, old);
     174             :   USE(old);
     175             : }
     176             : 
     177             : template <typename T,
     178             :           typename = typename std::enable_if<std::is_unsigned<T>::value>::type>
     179             : inline void CheckedDecrement(std::atomic<T>* number, T amount) {
     180             :   const T old = number->fetch_sub(amount);
     181             :   DCHECK_GE(old, amount);
     182             :   USE(old);
     183             : }
     184             : 
     185             : }  // namespace base
     186             : }  // namespace v8
     187             : 
     188             : #endif  // V8_BASE_ATOMIC_UTILS_H_

Generated by: LCOV version 1.10