LCOV - code coverage report
Current view: top level - gfx/skia/skia/include/private - SkAtomics.h (source / functions) Hit Total Coverage
Test: output.info Lines: 32 32 100.0 %
Date: 2017-07-14 16:53:18 Functions: 27 28 96.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2015 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #ifndef SkAtomics_DEFINED
       9             : #define SkAtomics_DEFINED
      10             : 
      11             : // This file is not part of the public Skia API.
      12             : #include "SkTypes.h"
      13             : #include <atomic>
      14             : 
      15             : // ~~~~~~~~ APIs ~~~~~~~~~
      16             : 
      17             : enum sk_memory_order {
      18             :     sk_memory_order_relaxed,
      19             :     sk_memory_order_consume,
      20             :     sk_memory_order_acquire,
      21             :     sk_memory_order_release,
      22             :     sk_memory_order_acq_rel,
      23             :     sk_memory_order_seq_cst,
      24             : };
      25             : 
      26             : template <typename T>
      27             : T sk_atomic_load(const T*, sk_memory_order = sk_memory_order_seq_cst);
      28             : 
      29             : template <typename T>
      30             : void sk_atomic_store(T*, T, sk_memory_order = sk_memory_order_seq_cst);
      31             : 
      32             : template <typename T>
      33             : T sk_atomic_fetch_add(T*, T, sk_memory_order = sk_memory_order_seq_cst);
      34             : 
      35             : template <typename T>
      36             : T sk_atomic_fetch_sub(T*, T, sk_memory_order = sk_memory_order_seq_cst);
      37             : 
      38             : template <typename T>
      39             : bool sk_atomic_compare_exchange(T*, T* expected, T desired,
      40             :                                 sk_memory_order success = sk_memory_order_seq_cst,
      41             :                                 sk_memory_order failure = sk_memory_order_seq_cst);
      42             : 
      43             : template <typename T>
      44             : T sk_atomic_exchange(T*, T, sk_memory_order = sk_memory_order_seq_cst);
      45             : 
      46             : // A little wrapper class for small T (think, builtins: int, float, void*) to
      47             : // ensure they're always used atomically.  This is our stand-in for std::atomic<T>.
      48             : // !!! Please _really_ know what you're doing if you change default_memory_order. !!!
      49             : template <typename T, sk_memory_order default_memory_order = sk_memory_order_seq_cst>
      50             : class SkAtomic : SkNoncopyable {
      51             : public:
      52        1078 :     SkAtomic() {}
      53         211 :     explicit SkAtomic(const T& val) : fVal(val) {}
      54             : 
      55             :     // It is essential we return by value rather than by const&.  fVal may change at any time.
      56        2187 :     T load(sk_memory_order mo = default_memory_order) const {
      57        2187 :         return sk_atomic_load(&fVal, mo);
      58             :     }
      59             : 
      60        4588 :     void store(const T& val, sk_memory_order mo = default_memory_order) {
      61        4588 :         sk_atomic_store(&fVal, val, mo);
      62        4588 :     }
      63             : 
      64             :     // Alias for .load(default_memory_order).
      65         256 :     MOZ_IMPLICIT operator T() const {
      66         256 :         return this->load();
      67             :     }
      68             : 
      69             :     // Alias for .store(v, default_memory_order).
      70        3296 :     T operator=(const T& v) {
      71        3296 :         this->store(v);
      72        3296 :         return v;
      73             :     }
      74             : 
      75             :     T fetch_add(const T& val, sk_memory_order mo = default_memory_order) {
      76             :         return sk_atomic_fetch_add(&fVal, val, mo);
      77             :     }
      78             : 
      79             :     T fetch_sub(const T& val, sk_memory_order mo = default_memory_order) {
      80             :         return sk_atomic_fetch_sub(&fVal, val, mo);
      81             :     }
      82             : 
      83          19 :     bool compare_exchange(T* expected, const T& desired,
      84             :                           sk_memory_order success = default_memory_order,
      85             :                           sk_memory_order failure = default_memory_order) {
      86          19 :         return sk_atomic_compare_exchange(&fVal, expected, desired, success, failure);
      87             :     }
      88             : private:
      89             :     T fVal;
      90             : };
      91             : 
      92             : // ~~~~~~~~ Implementations ~~~~~~~~~
      93             : 
      94             : template <typename T>
      95        2672 : T sk_atomic_load(const T* ptr, sk_memory_order mo) {
      96        2672 :     SkASSERT(mo == sk_memory_order_relaxed ||
      97             :              mo == sk_memory_order_seq_cst ||
      98             :              mo == sk_memory_order_acquire ||
      99             :              mo == sk_memory_order_consume);
     100        2672 :     const std::atomic<T>* ap = reinterpret_cast<const std::atomic<T>*>(ptr);
     101        2672 :     return std::atomic_load_explicit(ap, (std::memory_order)mo);
     102             : }
     103             : 
     104             : template <typename T>
     105        4599 : void sk_atomic_store(T* ptr, T val, sk_memory_order mo) {
     106        4599 :     SkASSERT(mo == sk_memory_order_relaxed ||
     107             :              mo == sk_memory_order_seq_cst ||
     108             :              mo == sk_memory_order_release);
     109        4599 :     std::atomic<T>* ap = reinterpret_cast<std::atomic<T>*>(ptr);
     110        4599 :     return std::atomic_store_explicit(ap, val, (std::memory_order)mo);
     111             : }
     112             : 
     113             : template <typename T>
     114        7553 : T sk_atomic_fetch_add(T* ptr, T val, sk_memory_order mo) {
     115             :     // All values of mo are valid.
     116        7553 :     std::atomic<T>* ap = reinterpret_cast<std::atomic<T>*>(ptr);
     117        7553 :     return std::atomic_fetch_add_explicit(ap, val, (std::memory_order)mo);
     118             : }
     119             : 
     120             : template <typename T>
     121             : T sk_atomic_fetch_sub(T* ptr, T val, sk_memory_order mo) {
     122             :     // All values of mo are valid.
     123             :     std::atomic<T>* ap = reinterpret_cast<std::atomic<T>*>(ptr);
     124             :     return std::atomic_fetch_sub_explicit(ap, val, (std::memory_order)mo);
     125             : }
     126             : 
     127             : template <typename T>
     128          19 : bool sk_atomic_compare_exchange(T* ptr, T* expected, T desired,
     129             :                                 sk_memory_order success,
     130             :                                 sk_memory_order failure) {
     131             :     // All values of success are valid.
     132          19 :     SkASSERT(failure == sk_memory_order_relaxed ||
     133             :              failure == sk_memory_order_seq_cst ||
     134             :              failure == sk_memory_order_acquire ||
     135             :              failure == sk_memory_order_consume);
     136          19 :     SkASSERT(failure <= success);
     137          19 :     std::atomic<T>* ap = reinterpret_cast<std::atomic<T>*>(ptr);
     138             :     return std::atomic_compare_exchange_strong_explicit(ap, expected, desired,
     139             :                                                         (std::memory_order)success,
     140          19 :                                                         (std::memory_order)failure);
     141             : }
     142             : 
     143             : template <typename T>
     144             : T sk_atomic_exchange(T* ptr, T val, sk_memory_order mo) {
     145             :     // All values of mo are valid.
     146             :     std::atomic<T>* ap = reinterpret_cast<std::atomic<T>*>(ptr);
     147             :     return std::atomic_exchange_explicit(ap, val, (std::memory_order)mo);
     148             : }
     149             : 
     150             : // ~~~~~~~~ Legacy APIs ~~~~~~~~~
     151             : 
     152             : // From here down we have shims for our old atomics API, to be weaned off of.
     153             : // We use the default sequentially-consistent memory order to make things simple
     154             : // and to match the practical reality of our old _sync and _win implementations.
     155             : 
     156        3816 : inline int32_t sk_atomic_inc(int32_t* ptr) { return sk_atomic_fetch_add(ptr, +1); }
     157        3526 : inline int32_t sk_atomic_dec(int32_t* ptr) { return sk_atomic_fetch_add(ptr, -1); }
     158             : 
     159             : #endif//SkAtomics_DEFINED

Generated by: LCOV version 1.13