$search
00001 // Copyright (c) 2009 Helge Bahmann 00002 // 00003 // Distributed under the Boost Software License, Version 1.0. 00004 // See accompanying file LICENSE_1_0.txt or copy at 00005 // http://www.boost.org/LICENSE_1_0.txt) 00006 00007 #include <boost/memory_order.hpp> 00008 #include "ros/atomic.h" 00009 #include <typeinfo> 00010 00011 #include <gtest/gtest.h> 00012 00013 using namespace ros; 00014 00015 00016 template<typename T> 00017 void test_atomic_arithmetic(void) 00018 { 00019 atomic<T> i(41); 00020 00021 T n; 00022 00023 fprintf(stderr, "Type=%s, size=%ld, atomic_size=%ld, lockfree=%d\n", 00024 typeid(T).name(), (long)sizeof(n), (long)sizeof(i), i.is_lock_free()); 00025 00026 ASSERT_TRUE(sizeof(i)>=sizeof(n)); 00027 00028 bool success; 00029 00030 n=i++; 00031 ASSERT_TRUE(i==42); 00032 ASSERT_TRUE(n==41); 00033 00034 n=i--; 00035 ASSERT_TRUE(n==42); 00036 ASSERT_TRUE(i==41); 00037 00038 n=++i; 00039 ASSERT_TRUE(i==42); 00040 ASSERT_TRUE(n==42); 00041 00042 n=--i; 00043 ASSERT_TRUE(n==41); 00044 ASSERT_TRUE(i==41); 00045 00046 n=i.fetch_and(15); 00047 ASSERT_TRUE(n==41); 00048 ASSERT_TRUE(i==9); 00049 00050 n=i.fetch_or(17); 00051 ASSERT_TRUE(n==9); 00052 ASSERT_TRUE(i==25); 00053 00054 n=i.fetch_xor(3); 00055 ASSERT_TRUE(n==25); 00056 ASSERT_TRUE(i==26); 00057 00058 n=i.exchange(12); 00059 ASSERT_TRUE(n==26); 00060 ASSERT_TRUE(i==12); 00061 00062 n=12; 00063 success=i.compare_exchange_strong(n, 17); 00064 ASSERT_TRUE(success); 00065 ASSERT_TRUE(n==12); 00066 ASSERT_TRUE(i==17); 00067 00068 n=12; 00069 success=i.compare_exchange_strong(n, 19); 00070 ASSERT_TRUE(!success); 00071 ASSERT_TRUE(n==17); 00072 ASSERT_TRUE(i==17); 00073 } 00074 00075 template<typename T> 00076 void test_atomic_base(void) 00077 { 00078 atomic<T> i; 00079 T n; 00080 00081 fprintf(stderr, "Type=%s, size=%ld, atomic_size=%ld, lockfree=%d\n", 00082 typeid(T).name(), (long)sizeof(n), (long)sizeof(i), i.is_lock_free()); 00083 00084 ASSERT_TRUE(sizeof(i)>=sizeof(n)); 00085 00086 bool success; 00087 00088 i.store((T)0); 00089 n=(T)40; 00090 success=i.compare_exchange_strong(n, (T)44 /*boost::memory_order_relaxed*/); 00091 ASSERT_TRUE(!success); 00092 ASSERT_TRUE(n==(T)0); 00093 ASSERT_TRUE(i.load()==(T)0); 00094 00095 n=(T)0; 00096 success=i.compare_exchange_strong(n, (T)44); 00097 ASSERT_TRUE(success); 00098 ASSERT_TRUE(n==(T)0); 00099 ASSERT_TRUE(i.load()==(T)44); 00100 00101 n=i.exchange((T)20); 00102 ASSERT_EQ(n, (T)44); 00103 ASSERT_TRUE(i.load()==(T)20); 00104 } 00105 00106 template<typename T> 00107 void test_atomic_ptr(void) 00108 { 00109 test_atomic_base<T *>(); 00110 00111 T array[10], *p; 00112 atomic<T *> ptr; 00113 00114 ptr=&array[0]; 00115 00116 p=ptr++; 00117 ASSERT_TRUE(p==&array[0]); 00118 ASSERT_TRUE(ptr==&array[1]); 00119 p=++ptr; 00120 ASSERT_TRUE(p==&array[2]); 00121 ASSERT_TRUE(ptr==&array[2]); 00122 00123 p=ptr.fetch_add(4); 00124 ASSERT_TRUE(p==&array[2]); 00125 ASSERT_TRUE(ptr==&array[6]); 00126 00127 p=ptr.fetch_sub(4); 00128 ASSERT_TRUE(p==&array[6]); 00129 ASSERT_TRUE(ptr==&array[2]); 00130 00131 p=ptr--; 00132 ASSERT_TRUE(p==&array[2]); 00133 ASSERT_TRUE(ptr==&array[1]); 00134 p=--ptr; 00135 ASSERT_TRUE(p==&array[0]); 00136 ASSERT_TRUE(ptr==&array[0]); 00137 } 00138 00139 template<> 00140 void test_atomic_base<bool>(void) 00141 { 00142 atomic<bool> i; 00143 bool n; 00144 00145 fprintf(stderr, "Type=bool, size=%ld, atomic_size=%ld, lockfree=%d\n", 00146 (long)sizeof(n), (long)sizeof(i), i.is_lock_free()); 00147 00148 ASSERT_TRUE(sizeof(i)>=sizeof(n)); 00149 00150 bool success; 00151 i=false; 00152 n=true; 00153 success=i.compare_exchange_strong(n, true); 00154 ASSERT_TRUE(!success); 00155 ASSERT_TRUE(n==false); 00156 ASSERT_TRUE(i==false); 00157 00158 n=false; 00159 success=i.compare_exchange_strong(n, true); 00160 ASSERT_TRUE(success); 00161 ASSERT_TRUE(n==false); 00162 ASSERT_TRUE(i==true); 00163 00164 n=i.exchange(false); 00165 ASSERT_TRUE(n==true); 00166 ASSERT_TRUE(i==false); 00167 } 00168 00169 void test_atomic_flag() 00170 { 00171 atomic_flag f; 00172 00173 ASSERT_TRUE(!f.test_and_set()); 00174 ASSERT_TRUE(f.test_and_set()); 00175 f.clear(); 00176 ASSERT_TRUE(!f.test_and_set()); 00177 } 00178 00179 struct Compound { 00180 int i; 00181 00182 inline bool operator==(const Compound &c) const {return i==c.i;} 00183 }; 00184 00185 void test_atomic_struct(void) 00186 { 00187 atomic<Compound> i; 00188 Compound n; 00189 00190 Compound zero={0}, one={1}, two={2}; 00191 00192 ASSERT_TRUE(sizeof(i)>=sizeof(n)); 00193 00194 bool success; 00195 00196 i.store(zero); 00197 n=one; 00198 success=i.compare_exchange_strong(n, two); 00199 ASSERT_TRUE(!success); 00200 ASSERT_TRUE(n==zero); 00201 ASSERT_TRUE(i.load()==zero); 00202 00203 n=zero; 00204 success=i.compare_exchange_strong(n, two); 00205 ASSERT_TRUE(success); 00206 ASSERT_TRUE(n==zero); 00207 ASSERT_TRUE(i.load()==two); 00208 00209 n=i.exchange(one); 00210 ASSERT_TRUE(n==two); 00211 ASSERT_TRUE(i.load()==one); 00212 } 00213 00214 enum TestEnum { 00215 Foo, Bar, Baz=1000 00216 }; 00217 00218 void test_fence() 00219 { 00220 atomic_thread_fence(memory_order_acquire); 00221 } 00222 00223 TEST(Atomic, all) 00224 { 00225 test_atomic_arithmetic<char>(); 00226 test_atomic_arithmetic<signed char>(); 00227 test_atomic_arithmetic<unsigned char>(); 00228 test_atomic_arithmetic<uint8_t>(); 00229 test_atomic_arithmetic<int8_t>(); 00230 test_atomic_arithmetic<short>(); 00231 test_atomic_arithmetic<unsigned short>(); 00232 test_atomic_arithmetic<uint16_t>(); 00233 test_atomic_arithmetic<int16_t>(); 00234 test_atomic_arithmetic<int>(); 00235 test_atomic_arithmetic<unsigned int>(); 00236 test_atomic_arithmetic<uint32_t>(); 00237 test_atomic_arithmetic<int32_t>(); 00238 test_atomic_arithmetic<long>(); 00239 test_atomic_arithmetic<unsigned long>(); 00240 test_atomic_arithmetic<uint64_t>(); 00241 test_atomic_arithmetic<int64_t>(); 00242 test_atomic_arithmetic<long long>(); 00243 test_atomic_arithmetic<unsigned long long>(); 00244 00245 test_atomic_struct(); 00246 00247 test_atomic_base<void *>(); 00248 test_atomic_ptr<int>(); 00249 test_atomic_base<bool>(); 00250 test_atomic_base<TestEnum>(); 00251 00252 atomic_thread_fence(memory_order_seq_cst); 00253 00254 test_fence(); 00255 00256 test_atomic_flag(); 00257 } 00258 00259 int main(int argc, char** argv) 00260 { 00261 testing::InitGoogleTest(&argc, argv); 00262 return RUN_ALL_TESTS(); 00263 }