LCOV - code coverage report
Current view: top level - src/base - atomic-utils.h (source / functions) Hit Total Coverage
Test: app.info Lines: 33 33 100.0 %
Date: 2017-04-26 Functions: 43 47 91.5 %

          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_ATOMIC_UTILS_H_
       6             : #define V8_ATOMIC_UTILS_H_
       7             : 
       8             : #include <limits.h>
       9             : 
      10             : #include "src/base/atomicops.h"
      11             : #include "src/base/macros.h"
      12             : 
      13             : namespace v8 {
      14             : namespace base {
      15             : 
      16             : template <class T>
      17             : class AtomicNumber {
      18             :  public:
      19      511063 :   AtomicNumber() : value_(0) {}
      20      877980 :   explicit AtomicNumber(T initial) : value_(initial) {}
      21             : 
      22             :   // Returns the value after incrementing.
      23             :   V8_INLINE T Increment(T increment) {
      24             :     return static_cast<T>(base::Barrier_AtomicIncrement(
      25    38232656 :         &value_, static_cast<base::AtomicWord>(increment)));
      26             :   }
      27             : 
      28             :   // Returns the value after decrementing.
      29             :   V8_INLINE T Decrement(T decrement) {
      30             :     return static_cast<T>(base::Barrier_AtomicIncrement(
      31     4072160 :         &value_, -static_cast<base::AtomicWord>(decrement)));
      32             :   }
      33             : 
      34             :   V8_INLINE T Value() const {
      35     3335375 :     return static_cast<T>(base::Acquire_Load(&value_));
      36             :   }
      37             : 
      38             :   V8_INLINE void SetValue(T new_value) {
      39     2384954 :     base::Release_Store(&value_, static_cast<base::AtomicWord>(new_value));
      40             :   }
      41             : 
      42             :   V8_INLINE T operator=(T value) {
      43             :     SetValue(value);
      44             :     return value;
      45             :   }
      46             : 
      47             :   V8_INLINE T operator+=(T value) { return Increment(value); }
      48             :   V8_INLINE T operator-=(T value) { return Decrement(value); }
      49             : 
      50             :  private:
      51             :   STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
      52             : 
      53             :   base::AtomicWord value_;
      54             : };
      55             : 
      56             : // This type uses no barrier accessors to change atomic word. Be careful with
      57             : // data races.
      58             : template <typename T>
      59             : class NoBarrierAtomicValue {
      60             :  public:
      61             :   NoBarrierAtomicValue() : value_(0) {}
      62             : 
      63             :   explicit NoBarrierAtomicValue(T initial)
      64             :       : value_(cast_helper<T>::to_storage_type(initial)) {}
      65             : 
      66             :   static NoBarrierAtomicValue* FromAddress(void* address) {
      67             :     return reinterpret_cast<base::NoBarrierAtomicValue<T>*>(address);
      68             :   }
      69             : 
      70             :   V8_INLINE bool TrySetValue(T old_value, T new_value) {
      71             :     return base::NoBarrier_CompareAndSwap(
      72             :                &value_, cast_helper<T>::to_storage_type(old_value),
      73    30873231 :                cast_helper<T>::to_storage_type(new_value)) ==
      74    31512821 :            cast_helper<T>::to_storage_type(old_value);
      75             :   }
      76             : 
      77             :   V8_INLINE T Value() const {
      78  1204927797 :     return cast_helper<T>::to_return_type(base::NoBarrier_Load(&value_));
      79             :   }
      80             : 
      81             :   V8_INLINE void SetValue(T new_value) {
      82             :     base::NoBarrier_Store(&value_, cast_helper<T>::to_storage_type(new_value));
      83             :   }
      84             : 
      85             :  private:
      86             :   STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
      87             : 
      88             :   template <typename S>
      89             :   struct cast_helper {
      90             :     static base::AtomicWord to_storage_type(S value) {
      91             :       return static_cast<base::AtomicWord>(value);
      92             :     }
      93   374133958 :     static S to_return_type(base::AtomicWord value) {
      94   374133958 :       return static_cast<S>(value);
      95             :     }
      96             :   };
      97             : 
      98             :   template <typename S>
      99             :   struct cast_helper<S*> {
     100    91427299 :     static base::AtomicWord to_storage_type(S* value) {
     101    91427299 :       return reinterpret_cast<base::AtomicWord>(value);
     102             :     }
     103   829411387 :     static S* to_return_type(base::AtomicWord value) {
     104   829411387 :       return reinterpret_cast<S*>(value);
     105             :     }
     106             :   };
     107             : 
     108             :   base::AtomicWord value_;
     109             : };
     110             : 
     111             : // Flag using T atomically. Also accepts void* as T.
     112             : template <typename T>
     113             : class AtomicValue {
     114             :  public:
     115   757803779 :   AtomicValue() : value_(0) {}
     116             : 
     117             :   explicit AtomicValue(T initial)
     118     1465295 :       : value_(cast_helper<T>::to_storage_type(initial)) {}
     119             : 
     120             :   V8_INLINE T Value() const {
     121  1461289066 :     return cast_helper<T>::to_return_type(base::Acquire_Load(&value_));
     122             :   }
     123             : 
     124             :   V8_INLINE bool TrySetValue(T old_value, T new_value) {
     125             :     return base::Release_CompareAndSwap(
     126             :                &value_, cast_helper<T>::to_storage_type(old_value),
     127   151416892 :                cast_helper<T>::to_storage_type(new_value)) ==
     128   150906812 :            cast_helper<T>::to_storage_type(old_value);
     129             :   }
     130             : 
     131             :   V8_INLINE void SetBits(T bits, T mask) {
     132             :     DCHECK_EQ(bits & ~mask, static_cast<T>(0));
     133             :     T old_value;
     134             :     T new_value;
     135   132715378 :     do {
     136             :       old_value = Value();
     137   132703409 :       new_value = (old_value & ~mask) | bits;
     138             :     } while (!TrySetValue(old_value, new_value));
     139             :   }
     140             : 
     141             :   V8_INLINE void SetBit(int bit) {
     142   128954161 :     SetBits(static_cast<T>(1) << bit, static_cast<T>(1) << bit);
     143             :   }
     144             : 
     145          14 :   V8_INLINE void ClearBit(int bit) { SetBits(0, 1 << bit); }
     146             : 
     147             :   V8_INLINE void SetValue(T new_value) {
     148    89503800 :     base::Release_Store(&value_, cast_helper<T>::to_storage_type(new_value));
     149             :   }
     150             : 
     151             :  private:
     152             :   STATIC_ASSERT(sizeof(T) <= sizeof(base::AtomicWord));
     153             : 
     154             :   template <typename S>
     155             :   struct cast_helper {
     156   531213005 :     static base::AtomicWord to_storage_type(S value) {
     157   531213005 :       return static_cast<base::AtomicWord>(value);
     158             :     }
     159   689169342 :     static S to_return_type(base::AtomicWord value) {
     160   689169342 :       return static_cast<S>(value);
     161             :     }
     162             :   };
     163             : 
     164             :   template <typename S>
     165             :   struct cast_helper<S*> {
     166    27276954 :     static base::AtomicWord to_storage_type(S* value) {
     167    27276954 :       return reinterpret_cast<base::AtomicWord>(value);
     168             :     }
     169   775323840 :     static S* to_return_type(base::AtomicWord value) {
     170   775323840 :       return reinterpret_cast<S*>(value);
     171             :     }
     172             :   };
     173             : 
     174             :   base::AtomicWord value_;
     175             : };
     176             : 
     177             : 
     178             : // See utils.h for EnumSet. Storage is always base::AtomicWord.
     179             : // Requirements on E:
     180             : // - No explicit values.
     181             : // - E::kLastValue defined to be the last actually used value.
     182             : //
     183             : // Example:
     184             : // enum E { kA, kB, kC, kLastValue = kC };
     185             : template <class E>
     186             : class AtomicEnumSet {
     187             :  public:
     188             :   explicit AtomicEnumSet(base::AtomicWord bits = 0) : bits_(bits) {}
     189             : 
     190             :   bool IsEmpty() const { return ToIntegral() == 0; }
     191             : 
     192             :   bool Contains(E element) const { return (ToIntegral() & Mask(element)) != 0; }
     193             :   bool ContainsAnyOf(const AtomicEnumSet& set) const {
     194             :     return (ToIntegral() & set.ToIntegral()) != 0;
     195             :   }
     196             : 
     197             :   void RemoveAll() { base::Release_Store(&bits_, 0); }
     198             : 
     199             :   bool operator==(const AtomicEnumSet& set) const {
     200             :     return ToIntegral() == set.ToIntegral();
     201             :   }
     202             : 
     203             :   bool operator!=(const AtomicEnumSet& set) const {
     204             :     return ToIntegral() != set.ToIntegral();
     205             :   }
     206             : 
     207             :   AtomicEnumSet<E> operator|(const AtomicEnumSet& set) const {
     208             :     return AtomicEnumSet<E>(ToIntegral() | set.ToIntegral());
     209             :   }
     210             : 
     211             : // The following operations modify the underlying storage.
     212             : 
     213             : #define ATOMIC_SET_WRITE(OP, NEW_VAL)                                     \
     214             :   do {                                                                    \
     215             :     base::AtomicWord old;                                                 \
     216             :     do {                                                                  \
     217             :       old = base::Acquire_Load(&bits_);                                   \
     218             :     } while (base::Release_CompareAndSwap(&bits_, old, old OP NEW_VAL) != \
     219             :              old);                                                        \
     220             :   } while (false)
     221             : 
     222             :   void Add(E element) { ATOMIC_SET_WRITE(|, Mask(element)); }
     223             : 
     224             :   void Add(const AtomicEnumSet& set) { ATOMIC_SET_WRITE(|, set.ToIntegral()); }
     225             : 
     226             :   void Remove(E element) { ATOMIC_SET_WRITE(&, ~Mask(element)); }
     227             : 
     228             :   void Remove(const AtomicEnumSet& set) {
     229             :     ATOMIC_SET_WRITE(&, ~set.ToIntegral());
     230             :   }
     231             : 
     232             :   void Intersect(const AtomicEnumSet& set) {
     233             :     ATOMIC_SET_WRITE(&, set.ToIntegral());
     234             :   }
     235             : 
     236             : #undef ATOMIC_SET_OP
     237             : 
     238             :  private:
     239             :   // Check whether there's enough storage to hold E.
     240             :   STATIC_ASSERT(E::kLastValue < (sizeof(base::AtomicWord) * CHAR_BIT));
     241             : 
     242             :   V8_INLINE base::AtomicWord ToIntegral() const {
     243             :     return base::Acquire_Load(&bits_);
     244             :   }
     245             : 
     246             :   V8_INLINE base::AtomicWord Mask(E element) const {
     247             :     return static_cast<base::AtomicWord>(1) << element;
     248             :   }
     249             : 
     250             :   base::AtomicWord bits_;
     251             : };
     252             : 
     253             : }  // namespace base
     254             : }  // namespace v8
     255             : 
     256             : #endif  // #define V8_ATOMIC_UTILS_H_

Generated by: LCOV version 1.10