medfall

A super great game engine
Log | Files | Refs

cli_volatile.hpp (3147B)


      1 /*  Relacy Race Detector
      2  *  Copyright (c) 2008-2013, Dmitry S. Vyukov
      3  *  All rights reserved.
      4  *  This software is provided AS-IS with no warranty, either express or implied.
      5  *  This software is distributed under a license and may not be copied,
      6  *  modified or distributed except as expressly authorized under the
      7  *  terms of the license contained in the file LICENSE in this distribution.
      8  */
      9 
     10 #ifndef RL_CLI_VOLATILE_HPP
     11 #define RL_CLI_VOLATILE_HPP
     12 #ifdef _MSC_VER
     13 #   pragma once
     14 #endif
     15 
     16 #include "base.hpp"
     17 #include "atomic.hpp"
     18 
     19 
     20 //!!! fix Java volatiles!
     21 // they must be modeled as seq_cst stores/loads
     22 
     23 namespace rl
     24 {
     25 
     26 template<typename T> class nvolatile;
     27 
     28 
     29 template<typename T>
     30 class nvolatile_proxy
     31 {
     32 public:
     33     typedef typename atomic_add_type<T>::type add_type;
     34     template<typename Y> friend class nvolatile;
     35 
     36     operator T () const
     37     {
     38         return load();
     39     }
     40 
     41     T operator = (T value)
     42     {
     43         store(value);
     44         return value;
     45     }
     46 
     47     T operator = (nvolatile_proxy const& r)
     48     {
     49         T const value = r.load();
     50         store(value);
     51         return *this;
     52     }
     53 
     54     T operator ++ (int)
     55     {
     56         T tmp = load();
     57         store(tmp + 1);
     58         return tmp;
     59     }
     60 
     61     T operator -- (int)
     62     {
     63         T tmp = load();
     64         store(tmp - 1);
     65         return tmp;
     66     }
     67 
     68     T operator ++ ()
     69     {
     70         T tmp = load();
     71         store(tmp + 1);
     72         return tmp + 1;
     73     }
     74 
     75     T operator -- ()
     76     {
     77         T tmp = load();
     78         store(tmp - 1);
     79         return tmp - 1;
     80     }
     81 
     82     T operator += (add_type value)
     83     {
     84         T tmp = load();
     85         store(tmp + value);
     86         return tmp + value;
     87     }
     88 
     89     T operator -= (add_type value)
     90     {
     91         T tmp = load();
     92         store(tmp - value);
     93         return tmp - value;
     94     }
     95 
     96 private:
     97     nvolatile<T>& var_;
     98     debug_info info_;
     99 
    100     nvolatile_proxy(nvolatile<T>& var, debug_info_param info)
    101         : var_(var)
    102         , info_(info)
    103     {
    104     }
    105 
    106     T load() const
    107     {
    108         return var_.load(mo_acquire, info_);
    109     }
    110 
    111     void store(T value)
    112     {
    113         var_.store(value, mo_release, info_);
    114     }
    115 };
    116 
    117 
    118 
    119 
    120 template<typename T>
    121 class nvolatile : public generic_atomic<T, true>
    122 {
    123 public:
    124     typedef nvolatile_proxy<T> proxy_t;
    125     friend class nvolatile_proxy<T>;
    126 
    127     nvolatile()
    128     {
    129     }
    130 
    131     explicit nvolatile(T value)
    132     {
    133         //??? whether here must be mo_relaxed or mo_release?
    134         this->store(value, mo_release, $);
    135     }
    136 
    137     nvolatile(nvolatile const& r)
    138     {
    139         T const value = r.load(mo_acquire, $);
    140         //??? whether here must be mo_relaxed or mo_release?
    141         this->store(value, mo_release, $);
    142     }
    143 
    144     nvolatile(proxy_t const& r)
    145     {
    146         T const value = r.var_.load(mo_acquire, r.info_);
    147         //??? whether here must be mo_relaxed or mo_release?
    148         this->store(value, mo_release, r.info_);
    149     }
    150 
    151     proxy_t operator () (debug_info_param info)
    152     {
    153         return proxy_t(*this, info);
    154     }
    155 };
    156 
    157 
    158 
    159 }
    160 
    161 #endif