/* standalone compile, from within this directory: g++ `pkg-config --cflags --libs libxml-2.0` `pkg-config --cflags --libs glibmm-2.4` -I../pbd -I../../build/libs/pbd -I. -o test2 test2.cc */ #include #include #include #include #include #include static int loop_count = 10000000; using namespace std; int64_t get_microseconds () { struct timespec ts; if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0) { /* EEEK! */ return 0; } return (int64_t)ts.tv_sec * 1000000 + (ts.tv_nsec / 1000); } void single_atomic () { struct thing { std::atomic v; thing() : v (0) { } }; thing t; int odd = 0; cout << "atomic is lock free ? " << t.v.is_lock_free() << endl; int64_t before = get_microseconds (); for (int n = 0; n < loop_count; ++n) { t.v = random (); t.v = t.v + 1; if (t.v % 2) { odd++; } } int64_t after = get_microseconds (); std::cout << "odd: " << odd << " usecs = " << after - before << std::endl; } void bitfields () { struct alignas(16) thing { int b : 1; int64_t v : 62; thing() : b (0), v (0) {} thing (int bc, int64_t vc) : b (bc), v (vc) {} thing operator+(int n) { return thing (b, v + n); } thing& operator=(thing const & other) { b = other.b; v = other.v; return *this; } }; thing t; int odd = 0; int64_t before = get_microseconds (); for (int n = 0; n < loop_count; ++n) { t.v = random (); t.v = t.v + 1; if (t.v % 2) { odd++; } } int64_t after = get_microseconds (); std::cout << "odd: " << odd << " usecs = " << after - before << std::endl; } void masks () { struct alignas(16) thing { private: int64_t v; bool is_beats() const { return v&(1LL<<62); } int64_t val() const { return v & ~(1LL<<62); } static int64_t build (bool bc, int64_t v) { return (bc ? (1LL<<62) : 0) | v; } public: thing() : v (0) {} thing (bool bc, int64_t vc) : v (build (bc, vc)) {} thing operator+(int n) const { return thing (is_beats(), val() + n); } thing& operator=(thing const & other) { v = other.v; return *this; } thing& operator+=(int64_t n) { v = build (is_beats(), val() + n); return *this; } thing& operator=(int64_t n) { v = build (is_beats(), n); return *this; } operator int64_t () const { return val(); } bool operator==(int64_t vv) const { return val() == vv; } }; thing t; int odd = 0; int64_t before = get_microseconds (); for (int n = 0; n < loop_count; ++n) { t = random (); t = t + 1; if ((t % 2) == 0) { odd++; } } int64_t after = get_microseconds (); std::cout << "odd: " << odd << " usecs = " << after - before << std::endl; } #include "pbd/int62.h" void atomic_masks () { int62_t t; int odd = 0; int64_t before = get_microseconds (); for (int n = 0; n < loop_count; ++n) { t = random (); t = t + 1; if ((t.val() % 2LL) == 0LL) { odd++; } } int64_t after = get_microseconds (); std::cout << "odd: " << odd << " usecs = " << after - before << std::endl; int62_t x; x = 1; cerr << "should be 1: " << x.val() << endl; x -= 1; cerr << "should be 0: " << x.val() << endl; x -= 1; cerr << "should be -1: " << x.val() << endl; x = int62_t::build (false, int62_t::min); cerr << "should be " << int62_t::min << ' ' << x.val() << " flagged ? " << x.flagged() << endl; x = int62_t::build (true, int62_t::min); cerr << "should still be " << int62_t::min << ' ' << x.val() << " and also flag: " << x.flagged() << endl; x += -x; cerr << "invert+add should be zero: " << x.val() << " and also flag: " << x.flagged() << endl; } void test_ints () { int62_t i62; int64_t i64 (0); int64_t arg; int64_t old62; int64_t old64; int skips = 0; for (int n = 0; n < loop_count; ++n) { arg = random(); old62 = i62.val(); old64 = i64; char opchar; int op = random() % 4; switch (op) { case 0: if (INT64_MAX - arg >= i64) { i64 += arg; if (i64 <= std::numeric_limits::max().val() && i64 >= std::numeric_limits::min().val()) { i62 += arg; } else { i64 = old64; skips++; } } opchar = '+'; break; case 1: if (INT64_MIN + arg <= i64) { i64 -= arg; if (i64 <= std::numeric_limits::max().val() && i64 >= std::numeric_limits::min().val()) { i62 -= arg; } else { i64 = old64; skips++; } } opchar = '-'; break; case 2: if (arg == 0) { i64 = 0; i62 = 0; } else { if (INT64_MAX / arg > i64) { i64 *= arg; if (i64 <= std::numeric_limits::max().val() && i64 >= std::numeric_limits::min().val()) { i62 *= arg; } else { i64 = old64; skips++; } } } opchar = '*'; break; case 3: if (arg == 0) { continue; } i64 /= arg; if (i64 <= std::numeric_limits::max().val() && i64 >= std::numeric_limits::min().val()) { i62 /= arg; } else { i64 = old64; skips++; } opchar = '/'; break; } if (i62.val() != i64) { cerr << "failure after " << n << " op = " << opchar << " arg " << arg << " old was " << old62 << " cur " << i62.val() << " vs. " << i64 << " whose old was " << old64 << endl; break; } // cerr << old64 << ' ' << opchar << ' ' << arg << " = " << i64 << endl; } cerr << "Had to skip " << skips << " of " << loop_count << endl; } int main (int argc, char *argv[]) { if (argc > 1) { loop_count = atoi (argv[1]); } srandom (time ((time_t *) 0)); single_atomic (); bitfields (); masks (); atomic_masks (); // test_ints (); return 0; }