Thread.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /* Copyright The kNet Project.
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License. */
  11. /** @file Thread.cpp
  12. @brief Implements platform-generic Thread functions. */
  13. #ifdef KNET_USE_BOOST
  14. #include <boost/thread/thread.hpp>
  15. #endif
  16. #include <sstream>
  17. #include "kNet/DebugMemoryLeakCheck.h"
  18. #include "kNet/Event.h" ///\todo Investigate the inclusion chain of these two files. Is this #include necessary?
  19. #include "kNet/NetworkLogging.h"
  20. #include "kNet/Thread.h"
  21. #include "kNet/PolledTimer.h"
  22. namespace kNet
  23. {
  24. std::string ThreadIdToString(const ThreadId &id)
  25. {
  26. std::stringstream ss;
  27. ss << id;
  28. return ss.str();
  29. }
  30. /// Suspends the thread until 'Resume()' is called. Call this function from the main thread.
  31. void Thread::Hold()
  32. {
  33. if (threadHoldEvent.Test())
  34. return;
  35. threadResumeEvent.Reset();
  36. threadHoldEvent.Reset();
  37. threadHoldEventAcked.Reset();
  38. threadHoldEvent.Set();
  39. PolledTimer timer;
  40. while(IsRunning())
  41. {
  42. bool success = threadHoldEventAcked.Wait(1000);
  43. if (success)
  44. break;
  45. }
  46. KNET_LOG(LogWaits, "Thread::Hold: Took %f msecs.", timer.MSecsElapsed());
  47. }
  48. /// Resumes the thread that is being held.
  49. void Thread::Resume()
  50. {
  51. threadResumeEvent.Set();
  52. threadHoldEvent.Reset();
  53. threadHoldEventAcked.Reset();
  54. }
  55. void Thread::CheckHold()
  56. {
  57. if (threadHoldEvent.Test())
  58. {
  59. KNET_LOG(LogVerbose, "Thread::CheckHold(): suspending thread. this: %p.", this);
  60. PolledTimer timer;
  61. while(!ShouldQuit())
  62. {
  63. threadHoldEventAcked.Set();
  64. bool success = threadResumeEvent.Wait(1000);
  65. if (success)
  66. break;
  67. }
  68. KNET_LOG(LogWaits, "Thread::CheckHold: Slept for %f msecs.", timer.MSecsElapsed());
  69. threadHoldEventAcked.Reset();
  70. }
  71. }
  72. // This code adapted from http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx "How to: Set a Thread Name in Native Code":
  73. #ifdef WIN32
  74. const DWORD MS_VC_EXCEPTION=0x406D1388;
  75. #pragma pack(push,8)
  76. typedef struct tagTHREADNAME_INFO
  77. {
  78. DWORD dwType; // Must be 0x1000.
  79. LPCSTR szName; // Pointer to name (in user addr space).
  80. DWORD dwThreadID; // Thread ID (-1=caller thread).
  81. DWORD dwFlags; // Reserved for future use, must be zero.
  82. } THREADNAME_INFO;
  83. #pragma pack(pop)
  84. void SetThreadName(DWORD dwThreadID, const char *threadName)
  85. {
  86. #ifdef _MSC_VER
  87. THREADNAME_INFO info;
  88. info.dwType = 0x1000;
  89. info.szName = threadName;
  90. info.dwThreadID = dwThreadID;
  91. info.dwFlags = 0;
  92. __try
  93. {
  94. RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
  95. }
  96. // __except(EXCEPTION_EXECUTE_HANDLER)
  97. __except(EXCEPTION_CONTINUE_EXECUTION)
  98. {
  99. }
  100. #else
  101. #warning SetThreadName undefined for current platform!
  102. #endif
  103. }
  104. #endif
  105. void Thread::SetName(const char *name)
  106. {
  107. // The thread name can only be set when it is ensured that Thread::Id() returns the proper Win32 thread ID
  108. #ifdef WIN32
  109. #if !defined(KNET_USE_BOOST) || !defined(KNET_ENABLE_WINXP_SUPPORT)
  110. SetThreadName(Id(), name);
  111. #endif
  112. #endif
  113. }
  114. } // ~kNet