Thread.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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. // Modified by Yao Wei Tjong for Urho3D
  14. #ifdef KNET_USE_BOOST
  15. #include <boost/thread/thread.hpp>
  16. #endif
  17. #include <sstream>
  18. #include "kNet/DebugMemoryLeakCheck.h"
  19. #include "kNet/Event.h" ///\todo Investigate the inclusion chain of these two files. Is this #include necessary?
  20. #include "kNet/NetworkLogging.h"
  21. #include "kNet/Thread.h"
  22. #include "kNet/PolledTimer.h"
  23. namespace kNet
  24. {
  25. std::string ThreadIdToString(const ThreadId &id)
  26. {
  27. std::stringstream ss;
  28. ss << id;
  29. return ss.str();
  30. }
  31. /// Suspends the thread until 'Resume()' is called. Call this function from the main thread.
  32. void Thread::Hold()
  33. {
  34. if (threadHoldEvent.Test())
  35. return;
  36. threadResumeEvent.Reset();
  37. threadHoldEvent.Reset();
  38. threadHoldEventAcked.Reset();
  39. threadHoldEvent.Set();
  40. PolledTimer timer;
  41. while(IsRunning())
  42. {
  43. bool success = threadHoldEventAcked.Wait(1000);
  44. if (success)
  45. break;
  46. }
  47. KNET_LOG(LogWaits, "Thread::Hold: Took %f msecs.", timer.MSecsElapsed());
  48. }
  49. /// Resumes the thread that is being held.
  50. void Thread::Resume()
  51. {
  52. threadResumeEvent.Set();
  53. threadHoldEvent.Reset();
  54. threadHoldEventAcked.Reset();
  55. }
  56. void Thread::CheckHold()
  57. {
  58. if (threadHoldEvent.Test())
  59. {
  60. KNET_LOG(LogVerbose, "Thread::CheckHold(): suspending thread. this: %p.", this);
  61. PolledTimer timer;
  62. while(!ShouldQuit())
  63. {
  64. threadHoldEventAcked.Set();
  65. bool success = threadResumeEvent.Wait(1000);
  66. if (success)
  67. break;
  68. }
  69. KNET_LOG(LogWaits, "Thread::CheckHold: Slept for %f msecs.", timer.MSecsElapsed());
  70. threadHoldEventAcked.Reset();
  71. }
  72. }
  73. // This code adapted from http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx "How to: Set a Thread Name in Native Code":
  74. #ifdef _WIN32
  75. const DWORD MS_VC_EXCEPTION=0x406D1388;
  76. #pragma pack(push,8)
  77. typedef struct tagTHREADNAME_INFO
  78. {
  79. DWORD dwType; // Must be 0x1000.
  80. LPCSTR szName; // Pointer to name (in user addr space).
  81. DWORD dwThreadID; // Thread ID (-1=caller thread).
  82. DWORD dwFlags; // Reserved for future use, must be zero.
  83. } THREADNAME_INFO;
  84. #pragma pack(pop)
  85. // Urho3D - avoid unnecessary warning in MinGW build
  86. #ifdef _MSC_VER
  87. void SetThreadName(DWORD dwThreadID, const char *threadName)
  88. {
  89. THREADNAME_INFO info;
  90. info.dwType = 0x1000;
  91. info.szName = threadName;
  92. info.dwThreadID = dwThreadID;
  93. info.dwFlags = 0;
  94. __try
  95. {
  96. RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
  97. }
  98. // __except(EXCEPTION_EXECUTE_HANDLER)
  99. __except(EXCEPTION_CONTINUE_EXECUTION)
  100. {
  101. }
  102. }
  103. #endif
  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 _MSC_VER
  109. #if !defined(KNET_USE_BOOST) || !defined(KNET_ENABLE_WINXP_SUPPORT)
  110. SetThreadName(Id(), name);
  111. #endif
  112. #endif
  113. }
  114. } // ~kNet