1 //----------------------------------------------------------------------------
2 /// @file atomic.hpp
3 /// @brief Basic layer for to simplify the use of atomic functions
4 /// @author Copyright(c) 2016 Francisco José Tapia (fjtapia@gmail.com )\n
5 ///         Distributed under the Boost Software License, Version 1.0.\n
6 ///         ( See accompanying file LICENSE_1_0.txt or copy at
7 ///           http://www.boost.org/LICENSE_1_0.txt  )
8 /// @version 0.1
9 ///
10 /// @remarks
11 //-----------------------------------------------------------------------------
12 #ifndef __BOOST_SORT_PARALLEL_DETAIL_UTIL_ATOMIC_HPP
13 #define __BOOST_SORT_PARALLEL_DETAIL_UTIL_ATOMIC_HPP
14 
15 #include <atomic>
16 #include <cassert>
17 #include <type_traits>
18 
19 namespace boost
20 {
21 namespace sort
22 {
23 namespace common
24 {
25 namespace util
26 {
27 //-----------------------------------------------------------------------------
28 //  function : atomic_read
29 /// @brief make the atomic read of an atomic variable, using a memory model
30 /// @param at_var : atomic variable to read
31 /// @return value obtained
32 //-----------------------------------------------------------------------------
33 template<typename T>
atomic_read(std::atomic<T> & at_var)34 inline T atomic_read(std::atomic<T> &at_var)
35 {
36     return std::atomic_load_explicit < T > (&at_var, std::memory_order_acquire);
37 };
38 //
39 //-----------------------------------------------------------------------------
40 //  function : atomic_add
41 /// @brief Add a number to an atomic variable, using a memory model
42 /// @param at_var : variable to add
43 /// @param num : value to add to at_var
44 /// @return result of the operation
45 //-----------------------------------------------------------------------------
46 template<typename T, typename T2>
atomic_add(std::atomic<T> & at_var,T2 num)47 inline T atomic_add(std::atomic<T> &at_var, T2 num)
48 {
49     static_assert (std::is_integral< T2 >::value, "Bad parameter");
50     return std::atomic_fetch_add_explicit <T>
51                                (&at_var, (T) num, std::memory_order_acq_rel);
52 };
53 //
54 //-----------------------------------------------------------------------------
55 //  function : atomic_sub
56 /// @brief Atomic subtract of an atomic variable using memory model
57 /// @param at_var : Varibale to subtract
58 /// @param num : value to sub to at_var
59 /// @return result of the operation
60 //-----------------------------------------------------------------------------
61 template<typename T, typename T2>
atomic_sub(std::atomic<T> & at_var,T2 num)62 inline T atomic_sub(std::atomic<T> &at_var, T2 num)
63 {
64     static_assert (std::is_integral< T2 >::value, "Bad parameter");
65     return std::atomic_fetch_sub_explicit <T>
66                                 (&at_var, (T) num, std::memory_order_acq_rel);
67 };
68 //
69 //-----------------------------------------------------------------------------
70 //  function : atomic_write
71 /// @brief Write a value in an atomic variable using memory model
72 /// @param at_var : varible to write
73 /// @param num : value to write in at_var
74 //-----------------------------------------------------------------------------
75 template<typename T, typename T2>
atomic_write(std::atomic<T> & at_var,T2 num)76 inline void atomic_write(std::atomic<T> &at_var, T2 num)
77 {
78     static_assert (std::is_integral< T2 >::value, "Bad parameter");
79     std::atomic_store_explicit <T>
80                                 (&at_var, (T) num, std::memory_order_release);
81 };
82 template<typename T>
83 struct counter_guard
84 {
85     typedef std::atomic<T> atomic_t;
86     atomic_t &count;
87 
counter_guardboost::sort::common::util::counter_guard88     counter_guard(atomic_t & counter): count(counter) { };
~counter_guardboost::sort::common::util::counter_guard89     ~counter_guard() {atomic_sub(count, 1); };
90 };
91 //
92 //****************************************************************************
93 };// End namespace util
94 };// End namespace common
95 };// End namespace sort
96 };// End namespace boost
97 //****************************************************************************
98 #endif
99