Go to the documentation of this file.00001
00002
00003
00004
00005
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 );
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 }