#include "asserts.h" #include "ThreadSharedState.h" #include "ThreadServer.h" #include "ThreadClient.h" #include "ThreadPriority.h" #include #include #include // test that we can build and tear down. static void test0() { assertEQ(ThreadSharedState::_dbgCount, 0); { std::shared_ptr noise = std::make_shared(); std::unique_ptr server(new ThreadServer(noise)); std::unique_ptr client(new ThreadClient(noise, std::move(server))); } assertEQ(ThreadSharedState::_dbgCount, 0); } static void test1() { for (int i = 0; i < 200; ++i) test0(); } /**************************************************************************/ // client will send to server class Test1Message : public ThreadMessage { public: Test1Message() : ThreadMessage(Type::TEST1) { } int payload = 0; }; // client will send to server class Test2Message : public ThreadMessage { public: Test2Message() : ThreadMessage(Type::TEST2) { } }; class TestServer : public ThreadServer { public: TestServer(std::shared_ptr state) : ThreadServer(state) { } void handleMessage(ThreadMessage* msg) override { switch (msg->type) { case ThreadMessage::Type::TEST1: { Test1Message * tstMsg = static_cast(msg); assertEQ(tstMsg->payload, nextExpectedPayload); ++nextExpectedPayload; tstMsg->payload += 1000; sendMessageToClient(tstMsg); // send back the modified one } break; default: assert(false); } } int nextExpectedPayload = 100; }; static void test2() { // Set up all the objects std::unique_ptr msg(new Test1Message()); std::shared_ptr state = std::make_shared(); std::unique_ptr server(new TestServer(state)); std::unique_ptr client(new ThreadClient(state, std::move(server))); for (int count = 0; count < 50; ++count) { msg->payload = 100 + count; const int expectedPayload = msg->payload + 1000; for (bool done = false; !done; ) { bool b = client->sendMessage(msg.get()); if (b) { done = true; } } for (bool done = false; !done; ) { auto rxmsg = client->getMessage(); if (rxmsg) { done = true; assert(rxmsg->type == ThreadMessage::Type::TEST1); Test1Message* tmsg = reinterpret_cast(rxmsg); assertEQ(tmsg->payload, expectedPayload); } } } } // not a real test static void test3() { bool b = ThreadPriority::boostNormal(); bool b2 = ThreadPriority::boostRealtime(); printf("\nnormal boost: %d\n", b); printf("realtime boost: %d\n", b2); ThreadPriority::restore(); } static std::atomic stopNow; static std::atomic count; static double xxx, yyy; static std::atomic slow; static std::atomic fast; //thread func static void t4(bool iAmIt,int boost) { // printf("t4 called with %d\n", iAmIt); if (iAmIt) { switch (boost) { case 0: printf("no boost\n"); break; case 1: printf("boosting\n"); ThreadPriority::boostNormal(); break; case 2: printf("boosting RT\n"); ThreadPriority::boostRealtime(); break; default: assert(false); } fflush(stdout); } while (!stopNow) { for (int i = 0; i < 100000; ++i) { yyy = yyy + (double) rand(); } if (iAmIt) { ++fast; } else { ++slow; } } } // runs all the test treads, returns ratio of work done in the default theads // and work done in test thread. static double test4sub(int boost) { stopNow = false; count = 0; xxx = 0; yyy = 0; slow = 0; fast = 0; int numSlow = 0; std::vector< std::shared_ptr> threads; threads.push_back(std::make_shared(t4, true, boost)); for (int i = 0; i < 9; ++i) { threads.push_back(std::make_shared(t4, false, 0)); ++numSlow; } printf("started all\n"); xxx = 0; yyy = 0; std::this_thread::sleep_for(std::chrono::seconds(20)); stopNow = true; for (auto thread : threads) { thread->join(); } ThreadPriority::restore(); const double ret = (double) slow / (double) fast; printf("slow/fast was %f (%d) ratio=%d\n", ret, (int) slow, numSlow); return ret; } static void test4() { printf("testing thread priorities, part1. will take a while\n"); fflush(stdout); const double ref = test4sub(0); printf("testing thread priorities, part2. will take a while\n"); fflush(stdout); const double boosted = test4sub(1); printf("testing thread priorities, part3. will take a while\n"); fflush(stdout); const double boostedRT = test4sub(2); printf("ref = %f, boosted = %f rt=%f\n", ref, boosted, boostedRT); fflush(stdout); } #ifdef ARCH_WIN static void test5() { ThreadPriority::boostRealtimeWindows(); } #endif /*****************************************************************/ void testThread(bool extended) { assertEQ(ThreadSharedState::_dbgCount, 0); assertEQ(ThreadMessage::_dbgCount, 0); test0(); test1(); test2(); test3(); if (extended) { test4(); } #ifdef ARCH_WIN test5(); #endif assertEQ(ThreadSharedState::_dbgCount, 0); assertEQ(ThreadMessage::_dbgCount, 0); }