pion-net  4.0.9
cas.hpp
1 // Copyright (C) 2007, 2008, 2009 Tim Blechmann & Thomas Grill
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 
7 // Disclaimer: Not a Boost library.
8 
9 #ifndef BOOST_LOCKFREE_CAS_HPP_INCLUDED
10 #define BOOST_LOCKFREE_CAS_HPP_INCLUDED
11 
12 #include <boost/lockfree/detail/prefix.hpp>
13 #include <boost/interprocess/detail/atomic.hpp>
14 #include <boost/detail/lightweight_mutex.hpp>
15 #include <boost/static_assert.hpp>
16 
17 #include <boost/cstdint.hpp>
18 
19 #include <boost/mpl/map.hpp>
20 #include <boost/mpl/at.hpp>
21 #include <boost/mpl/if.hpp>
22 #include <boost/mpl/long.hpp>
23 
24 #ifdef __SSE2__
25 #include "emmintrin.h"
26 #endif
27 
28 namespace boost
29 {
30 namespace lockfree
31 {
32 
33 inline void memory_barrier(void)
34 {
35 #if defined(__SSE2__)
36  _mm_mfence();
37 
38 #elif defined(__GNUC__) && ( (__GNUC__ > 4) || ((__GNUC__ >= 4) && \
39  (__GNUC_MINOR__ >= 1))) \
40  || defined(__INTEL_COMPILER)
41  __sync_synchronize();
42 #elif defined(__GNUC__) && defined (__i386__)
43  asm volatile("lock; addl $0,0(%%esp)":::"memory");
44 #elif defined(_MSC_VER) && (_MSC_VER >= 1300)
45  _ReadWriteBarrier();
46 #elif defined(__APPLE__)
47  OSMemoryBarrier();
48 #elif defined(AO_HAVE_nop_full)
49  AO_nop_full();
50 #else
51 # warning "no memory barrier implemented for this platform"
52 #endif
53 }
54 
55 inline void read_memory_barrier(void)
56 {
57 #if defined(__SSE2__)
58  _mm_lfence();
59 #else
60  memory_barrier();
61 #endif
62 }
63 
64 template <typename C>
66 {
67  static inline bool cas(C * addr, C old, C nw)
68  {
69  static boost::detail::lightweight_mutex guard;
70  boost::detail::lightweight_mutex::scoped_lock lock(guard);
71 
72  if (*addr == old)
73  {
74  *addr = nw;
75  return true;
76  }
77  else
78  return false;
79  }
80 
81  typedef C cas_type;
82 };
83 
84 
85 template <typename C>
86 inline bool atomic_cas_emulation(C * addr, C old, C nw)
87 {
88  return atomic_cas_emulator<C>::cas(addr, old, nw);
89 }
90 
91 using boost::uint32_t;
92 using boost::uint64_t;
93 
95 {
96  static inline bool cas(volatile uint32_t * addr,
97  uint64_t const & old,
98  uint64_t const & nw)
99  {
100 #if defined(__GNUC__) && ( (__GNUC__ > 4) || ((__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)) ) || defined(__INTEL_COMPILER)
101  return __sync_bool_compare_and_swap(addr, old, nw);
102 #else
103  return boost::interprocess::detail::atomic_cas32(addr, old, nw) == old;
104 #endif
105  }
106  typedef uint32_t cas_type;
107 
108  static const bool is_lockfree = true;
109 };
110 
112 {
113  typedef uint64_t cas_type;
114 
115  static inline bool cas(volatile uint64_t * addr,
116  uint64_t const & old,
117  uint64_t const & nw)
118  {
119 #if defined(__GNUC__) && ( (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 1)) \
120  || ((__GNUC__ == 4) && (__GNUC_MINOR__ == 1) && defined(__x86_64__)) ) \
121  || defined(__INTEL_COMPILER)
122  return __sync_bool_compare_and_swap(addr, old, nw);
123 #elif defined(_M_IX86)
124  return InterlockedCompareExchange(reinterpret_cast<volatile LONG*>(addr),
125  reinterpret_cast<LONG>(nw),
126  reinterpret_cast<LONG>(old)) == old;
127 #elif defined(_M_X64)
128  return InterlockedCompareExchange(reinterpret_cast<volatile LONG*>(addr),
129  reinterpret_cast<LONG>(nw),
130  reinterpret_cast<LONG>(old)) == old;
131 #else
132 #define CAS_BLOCKING
133 #warning ("blocking CAS emulation")
134  return atomic_cas_emulation((uint64_t *)addr, old, nw);
135 #endif
136  }
137 
138 #ifdef CAS_BLOCKING
139 #undef CAS_BLOCKING
140  static const bool is_lockfree = false;
141 #else
142  static const bool is_lockfree = true;
143 #endif
144 };
145 
147 {
148 #if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
149  typedef int cas_type __attribute__ ((mode (TI)));
150 #else
151  struct cas_type
152  {
153  bool operator==(cas_type const & rhs)
154  {
155  return (data[0] == rhs.data[0]) &&
156  (data[1] == rhs.data[1]);
157  }
158 
159  uint64_t data[2];
160  };
161 #endif
162 
163  static inline bool cas(volatile cas_type * addr, cas_type const & old, cas_type const & nw)
164  {
165 #if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
166  return __sync_bool_compare_and_swap_16(addr, old, nw);
167 #else
168 #define CAS_BLOCKING
169 //#warning ("blocking CAS emulation")
170  return atomic_cas_emulation((cas_type*)addr, old, nw);
171 #endif
172  }
173 
174 #ifdef CAS_BLOCKING
175 #undef CAS_BLOCKING
176  static const bool is_lockfree = false;
177 #else
178  static const bool is_lockfree = true;
179 #endif
180 };
181 
182 namespace detail
183 {
184 using namespace boost::mpl;
185 
186 template<typename C>
188 {
189 private:
190  typedef map3<pair<long_<4>, atomic_cas32>,
191  pair<long_<8>, atomic_cas64>,
192  pair<long_<16>, atomic_cas128>
193  > cas_map;
194 
195  typedef typename at<cas_map, long_<sizeof(C)> >::type atomic_cas_t;
196 
197  typedef typename if_<has_key<cas_map, long_<sizeof(C)> >,
198  atomic_cas_t,
199  atomic_cas_emulator<C> >::type cas_t;
200 
201  typedef typename cas_t::cas_type cas_value_t;
202 
203 public:
204  static inline bool cas(volatile C * addr, C const & old, C const & nw)
205  {
206  return cas_t::cas((volatile cas_value_t*)addr,
207  *(cas_value_t*)&old,
208  *(cas_value_t*)&nw);
209  }
210 
211  static const bool is_lockfree = cas_t::is_lockfree;
212 };
213 
214 } /* namespace detail */
215 
216 using detail::atomic_cas;
217 
218 template <typename C>
219 inline bool cas(volatile C * addr, C const & old, C const & nw)
220 {
221  return atomic_cas<C>::cas(addr, old, nw);
222 }
223 
224 } /* namespace lockfree */
225 } /* namespace boost */
226 
227 #endif /* BOOST_LOCKFREE_CAS_HPP_INCLUDED */