You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

234 lines
5.8KB

  1. #include "asserts.h"
  2. #include "ThreadSharedState.h"
  3. #include "ThreadServer.h"
  4. #include "ThreadClient.h"
  5. #include "ThreadPriority.h"
  6. #include <assert.h>
  7. #include <memory>
  8. #include <vector>
  9. // test that we can build and tear down.
  10. static void test0()
  11. {
  12. assertEQ(ThreadSharedState::_dbgCount, 0);
  13. {
  14. std::shared_ptr<ThreadSharedState> noise = std::make_shared<ThreadSharedState>();
  15. std::unique_ptr<ThreadServer> server(new ThreadServer(noise));
  16. std::unique_ptr<ThreadClient> client(new ThreadClient(noise, std::move(server)));
  17. }
  18. assertEQ(ThreadSharedState::_dbgCount, 0);
  19. }
  20. static void test1()
  21. {
  22. for (int i = 0; i < 200; ++i)
  23. test0();
  24. }
  25. /**************************************************************************/
  26. // client will send to server
  27. class Test1Message : public ThreadMessage
  28. {
  29. public:
  30. Test1Message() : ThreadMessage(Type::TEST1)
  31. {
  32. }
  33. int payload = 0;
  34. };
  35. // client will send to server
  36. class Test2Message : public ThreadMessage
  37. {
  38. public:
  39. Test2Message() : ThreadMessage(Type::TEST2)
  40. {
  41. }
  42. };
  43. class TestServer : public ThreadServer
  44. {
  45. public:
  46. TestServer(std::shared_ptr<ThreadSharedState> state) : ThreadServer(state)
  47. {
  48. }
  49. void handleMessage(ThreadMessage* msg) override
  50. {
  51. switch (msg->type) {
  52. case ThreadMessage::Type::TEST1:
  53. {
  54. Test1Message * tstMsg = static_cast<Test1Message *>(msg);
  55. assertEQ(tstMsg->payload, nextExpectedPayload);
  56. ++nextExpectedPayload;
  57. tstMsg->payload += 1000;
  58. sendMessageToClient(tstMsg); // send back the modified one
  59. }
  60. break;
  61. default:
  62. assert(false);
  63. }
  64. }
  65. int nextExpectedPayload = 100;
  66. };
  67. static void test2()
  68. {
  69. // Set up all the objects
  70. std::unique_ptr<Test1Message> msg(new Test1Message());
  71. std::shared_ptr<ThreadSharedState> state = std::make_shared<ThreadSharedState>();
  72. std::unique_ptr<TestServer> server(new TestServer(state));
  73. std::unique_ptr<ThreadClient> client(new ThreadClient(state, std::move(server)));
  74. for (int count = 0; count < 50; ++count) {
  75. msg->payload = 100 + count;
  76. const int expectedPayload = msg->payload + 1000;
  77. for (bool done = false; !done; ) {
  78. bool b = client->sendMessage(msg.get());
  79. if (b) {
  80. done = true;
  81. }
  82. }
  83. for (bool done = false; !done; ) {
  84. auto rxmsg = client->getMessage();
  85. if (rxmsg) {
  86. done = true;
  87. assert(rxmsg->type == ThreadMessage::Type::TEST1);
  88. Test1Message* tmsg = reinterpret_cast<Test1Message *>(rxmsg);
  89. assertEQ(tmsg->payload, expectedPayload);
  90. }
  91. }
  92. }
  93. }
  94. // not a real test
  95. static void test3()
  96. {
  97. bool b = ThreadPriority::boostNormal();
  98. bool b2 = ThreadPriority::boostRealtime();
  99. printf("\nnormal boost: %d\n", b);
  100. printf("realtime boost: %d\n", b2);
  101. ThreadPriority::restore();
  102. }
  103. static std::atomic<bool> stopNow;
  104. static std::atomic<int> count;
  105. static double xxx, yyy;
  106. static std::atomic<int> slow;
  107. static std::atomic<int> fast;
  108. //thread func
  109. static void t4(bool iAmIt,int boost)
  110. {
  111. // printf("t4 called with %d\n", iAmIt);
  112. if (iAmIt) {
  113. switch (boost) {
  114. case 0:
  115. printf("no boost\n");
  116. break;
  117. case 1:
  118. printf("boosting\n");
  119. ThreadPriority::boostNormal();
  120. break;
  121. case 2:
  122. printf("boosting RT\n");
  123. ThreadPriority::boostRealtime();
  124. break;
  125. default:
  126. assert(false);
  127. }
  128. fflush(stdout);
  129. }
  130. while (!stopNow) {
  131. for (int i = 0; i < 100000; ++i) {
  132. yyy = yyy + (double) rand();
  133. }
  134. if (iAmIt) {
  135. ++fast;
  136. } else {
  137. ++slow;
  138. }
  139. }
  140. }
  141. // runs all the test treads, returns ratio of work done in the default theads
  142. // and work done in test thread.
  143. static double test4sub(int boost)
  144. {
  145. stopNow = false;
  146. count = 0;
  147. xxx = 0;
  148. yyy = 0;
  149. slow = 0;
  150. fast = 0;
  151. int numSlow = 0;
  152. std::vector< std::shared_ptr<std::thread>> threads;
  153. threads.push_back(std::make_shared<std::thread>(t4, true, boost));
  154. for (int i = 0; i < 9; ++i) {
  155. threads.push_back(std::make_shared<std::thread>(t4, false, 0));
  156. ++numSlow;
  157. }
  158. printf("started all\n");
  159. xxx = 0;
  160. yyy = 0;
  161. std::this_thread::sleep_for(std::chrono::seconds(20));
  162. stopNow = true;
  163. for (auto thread : threads) {
  164. thread->join();
  165. }
  166. ThreadPriority::restore();
  167. const double ret = (double) slow / (double) fast;
  168. printf("slow/fast was %f (%d) ratio=%d\n", ret, (int) slow, numSlow);
  169. return ret;
  170. }
  171. static void test4()
  172. {
  173. printf("testing thread priorities, part1. will take a while\n"); fflush(stdout);
  174. const double ref = test4sub(0);
  175. printf("testing thread priorities, part2. will take a while\n"); fflush(stdout);
  176. const double boosted = test4sub(1);
  177. printf("testing thread priorities, part3. will take a while\n"); fflush(stdout);
  178. const double boostedRT = test4sub(2);
  179. printf("ref = %f, boosted = %f rt=%f\n", ref, boosted, boostedRT); fflush(stdout);
  180. }
  181. #ifdef ARCH_WIN
  182. static void test5()
  183. {
  184. ThreadPriority::boostRealtimeWindows();
  185. }
  186. #endif
  187. /*****************************************************************/
  188. void testThread(bool extended)
  189. {
  190. assertEQ(ThreadSharedState::_dbgCount, 0);
  191. assertEQ(ThreadMessage::_dbgCount, 0);
  192. test0();
  193. test1();
  194. test2();
  195. test3();
  196. if (extended) {
  197. test4();
  198. }
  199. #ifdef ARCH_WIN
  200. test5();
  201. #endif
  202. assertEQ(ThreadSharedState::_dbgCount, 0);
  203. assertEQ(ThreadMessage::_dbgCount, 0);
  204. }