| | |
| | | #include "robust.h" |
| | | #include "util.h" |
| | | #include <boost/circular_buffer.hpp> |
| | | |
| | | using namespace robust; |
| | | |
| | | typedef CircularBuffer<int64_t, Allocator<int64_t>> Rcb; |
| | | Rcb *GetRCBImpl(SharedMemory &shm, const int nelem) |
| | | { |
| | | int cap = nelem + 1; |
| | | typedef uint64_t Data; |
| | | auto size = sizeof(Rcb) + sizeof(Data) * cap; |
| | | void *p = shm.Alloc(size); |
| | | if (p) { |
| | | return new (p) Rcb(cap, shm.get_segment_manager()); |
| | | } |
| | | return nullptr; |
| | | } |
| | | Rcb *GetRCB(SharedMemory &shm, const int nelem) |
| | | { |
| | | void **pStore = shm.FindOrCreate<void *>("test_rcb_pointer", nullptr); |
| | | if (pStore) { |
| | | if (!*pStore) { |
| | | *pStore = GetRCBImpl(shm, nelem); |
| | | } |
| | | return (Rcb *) *pStore; |
| | | } |
| | | return nullptr; |
| | | } |
| | | enum { |
| | | eLockerBits = 32, |
| | | eLockerMask = MaskBits(sizeof(int) * 8), |
| | | }; |
| | | |
| | | void MySleep() |
| | | { |
| | | std::this_thread::sleep_for(2us); |
| | | } |
| | | |
| | | BOOST_AUTO_TEST_CASE(RobustTest) |
| | | ///////////////////////////////////////////////////////////////////////////////////////// |
| | | |
| | | BOOST_AUTO_TEST_CASE(InitTest) |
| | | { |
| | | AtomicReqRep rr; |
| | | auto client = [&]() { |
| | | for (int i = 0; i < 5; ++i) { |
| | | int64_t reply = 0; |
| | | bool r = rr.ClientRequest(i, reply); |
| | | printf("init request %d, %s, reply %d\n", i, (r ? "ok" : "failed"), reply); |
| | | } |
| | | }; |
| | | |
| | | bool run = true; |
| | | auto server = [&]() { |
| | | auto onReq = [](int64_t req) { return req + 100; }; |
| | | while (run) { |
| | | rr.ServerProcess(onReq); |
| | | } |
| | | }; |
| | | |
| | | ThreadManager clients, servers; |
| | | servers.Launch(server); |
| | | for (int i = 0; i < 2; ++i) { |
| | | clients.Launch(client); |
| | | } |
| | | clients.WaitAll(); |
| | | run = false; |
| | | servers.WaitAll(); |
| | | } |
| | | |
| | | BOOST_AUTO_TEST_CASE(QueueTest) |
| | | { |
| | | const int nthread = 100; |
| | | const uint64_t nmsg = 1000 * 1000 * 10; |
| | | |
| | | SharedMemory &shm = TestShm(); |
| | | shm.Remove(); |
| | | pid_t pid = getpid(); |
| | | printf("pid : %d\n", pid); |
| | | auto Access = [](pid_t pid) { |
| | | char buf[100] = {0}; |
| | | sprintf(buf, "/proc/%d/stat", pid); |
| | | int r = access(buf, F_OK); |
| | | printf("access %d\n", r); |
| | | }; |
| | | Access(pid); |
| | | Access(pid + 1); |
| | | // Sleep(10s); |
| | | // return; |
| | | // return; ///////////////////////////////////////////////// |
| | | int64_t i64 = 0; |
| | | char c = 0; |
| | | for (int i = 0; i < 256; ++i) { |
| | | c = i; |
| | | i64 = int64_t(c) << 1; |
| | | BOOST_CHECK_EQUAL(c, (i64 >> 1)); |
| | | uint64_t u64 = i; |
| | | BOOST_CHECK_EQUAL((u64 & 255), i); |
| | | } |
| | | |
| | | int nelement = 640; |
| | | auto rcb = GetRCB(shm, nelement); |
| | | BOOST_CHECK(rcb != nullptr); |
| | | BOOST_CHECK(rcb->empty()); |
| | | BOOST_CHECK(rcb->push_back(1)); |
| | | BOOST_CHECK(rcb->size() == 1); |
| | | int64_t d; |
| | | BOOST_CHECK(rcb->pop_front(d)); |
| | | BOOST_CHECK(rcb->empty()); |
| | | |
| | | const uint64_t nmsg = 1000 * 1000 * 1; |
| | | uint64_t correct_total = nmsg * (nmsg - 1) / 2; |
| | | std::atomic<uint64_t> total(0); |
| | | std::atomic<uint64_t> nwrite(0); |
| | | std::atomic<uint64_t> writedone(0); |
| | | |
| | | typedef AtomicQ63 Rcb; |
| | | |
| | | Rcb tmp; |
| | | BOOST_CHECK(tmp.push(1)); |
| | | int64_t d; |
| | | BOOST_CHECK(tmp.pop(d)); |
| | | |
| | | NamedShmObject<Rcb> rcb(shm, "test_rcb", eOpenOrCreate); |
| | | bool try_more = true; |
| | | |
| | | auto Writer = [&]() { |
| | | uint64_t n = 0; |
| | | while ((n = nwrite++) < nmsg) { |
| | | while (!rcb->push_back(n)) { |
| | | while (!rcb->push(n, try_more)) { |
| | | // MySleep(); |
| | | } |
| | | ++writedone; |
| | |
| | | auto Reader = [&]() { |
| | | while (nread.load() < nmsg) { |
| | | int64_t d; |
| | | if (rcb->pop_front(d)) { |
| | | if (rcb->pop(d, try_more)) { |
| | | ++nread; |
| | | total += d; |
| | | } else { |
| | | MySleep(); |
| | | // MySleep(); |
| | | } |
| | | } |
| | | }; |
| | |
| | | next += 1s; |
| | | auto w = writedone.load(); |
| | | auto r = nread.load(); |
| | | printf("write: %6ld, spd: %6ld, read: %6ld, spd: %6ld , queue size: %d\n", w, w - lw, r, r - lr, rcb->size()); |
| | | printf("write: %6ld, spd: %6ld, read: %6ld, spd: %6ld\n", |
| | | w, w - lw, r, r - lr); |
| | | lw = w; |
| | | lr = r; |
| | | } while (nread.load() < nmsg); |
| | | }; |
| | | |
| | | ThreadManager threads; |
| | | boost::timer::auto_cpu_timer timer; |
| | | printf("Testing Robust Buffer, msgs %ld, queue size: %d \n", nmsg, nelement); |
| | | threads.Launch(status); |
| | | for (int i = 0; i < 10; ++i) { |
| | | threads.Launch(Reader); |
| | | threads.Launch(Writer); |
| | | std::thread st(status); |
| | | { |
| | | ThreadManager threads; |
| | | boost::timer::auto_cpu_timer timer; |
| | | // printf("Testing Robust Buffer, msgs %ld, queue size: %d, threads: %d \n", nmsg, Rcb::capacity, nthread); |
| | | printf("Testing Robust Buffer, msgs %ld, queue size: %d, threads: %d \n", nmsg, 16, nthread); |
| | | for (int i = 0; i < nthread; ++i) { |
| | | threads.Launch(Reader); |
| | | threads.Launch(Writer); |
| | | } |
| | | threads.WaitAll(); |
| | | } |
| | | threads.WaitAll(); |
| | | st.join(); |
| | | printf("total: %ld, expected: %ld\n", total.load(), correct_total); |
| | | BOOST_CHECK_EQUAL(total.load(), correct_total); |
| | | } |
| | | } |