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.

90 lines
2.5KB

  1. #include <assert.h>
  2. #include "ThreadSharedState.h"
  3. std::atomic<int> ThreadSharedState::_dbgCount;
  4. std::atomic<int> ThreadMessage::_dbgCount;
  5. #include <iostream>
  6. #include <chrono>
  7. #include <thread>
  8. ThreadMessage* ThreadSharedState::server_waitForMessageOrShutdown()
  9. {
  10. // printf("wait\n"); fflush(stdout);
  11. std::unique_lock<std::mutex> guard(mailboxMutex); // grab the mutex that protects condition
  12. ThreadMessage* returnMessage = nullptr;
  13. for (bool done = false; !done; ) {
  14. if (serverStopRequested.load()) {
  15. done = true;
  16. } else {
  17. returnMessage = mailboxClient2Server.load();
  18. if (returnMessage) {
  19. done = true;
  20. }
  21. }
  22. if (!done) {
  23. mailboxCondition.wait(guard);
  24. }
  25. }
  26. mailboxClient2Server.store(nullptr);
  27. return returnMessage;
  28. }
  29. void ThreadSharedState::client_askServerToStop()
  30. {
  31. serverStopRequested.store(true); // ask server to stop
  32. std::unique_lock<std::mutex> guard(mailboxMutex); // grab the mutex
  33. mailboxCondition.notify_all(); // wake up server
  34. }
  35. ThreadMessage* ThreadSharedState::client_pollMessage()
  36. {
  37. ThreadMessage* msg = nullptr;
  38. // grab lock
  39. std::unique_lock<std::mutex> guard(mailboxMutex);
  40. msg = mailboxServer2Client.load();
  41. if (msg) {
  42. mailboxServer2Client.store(nullptr);
  43. }
  44. return msg;
  45. }
  46. // signal in lock
  47. bool ThreadSharedState::client_trySendMessage(ThreadMessage* msg)
  48. {
  49. assert(serverRunning.load());
  50. // If the client tries to send a message before the previous one is read, the
  51. // call will fail and the client must try again.
  52. if (mailboxClient2Server.load()) {
  53. return false;
  54. }
  55. // Write to mailbox (condition) in lock
  56. std::unique_lock<std::mutex> guard(mailboxMutex, std::defer_lock);
  57. // We must use a try_lock here, as calling regular lock() could cause a priority inversion.
  58. bool didLock = guard.try_lock();
  59. if (!didLock) {
  60. return false;
  61. }
  62. assert(guard.owns_lock());
  63. assert(!mailboxClient2Server.load()); // if there is still a message there we are out of sync
  64. mailboxClient2Server.store(msg);
  65. mailboxCondition.notify_all();
  66. return true;
  67. }
  68. void ThreadSharedState::server_sendMessage(ThreadMessage* msg)
  69. {
  70. std::unique_lock<std::mutex> guard(mailboxMutex);
  71. assert(mailboxServer2Client.load() == nullptr);
  72. mailboxServer2Client.store(msg);
  73. }