Critical.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #include "Critical.h"
  2. #include <iostream>
  3. #include <time.h>
  4. #include "Globals.h"
  5. #include "Thread.h"
  6. using namespace Framework;
  7. // Inhalt der Critical class aus Critical.h
  8. // Konstructor
  9. Critical::Critical()
  10. {
  11. InitializeCriticalSection(&cs);
  12. owner = 0;
  13. lockCount = 0;
  14. id = (int)time(0);
  15. }
  16. // Destructor
  17. Critical::~Critical()
  18. {
  19. DeleteCriticalSection(&cs);
  20. }
  21. pthread_t CachedCurrentThread()
  22. {
  23. volatile thread_local static pthread_t t = GetCurrentThread();
  24. return (pthread_t)t;
  25. }
  26. // sperrt das Objekt
  27. void Critical::lock()
  28. {
  29. getThreadRegister()->lock();
  30. Thread* tmp = getThreadRegister()->zThread(CachedCurrentThread());
  31. if (tmp) tmp->addCriticalLock();
  32. getThreadRegister()->unlock();
  33. EnterCriticalSection(&cs);
  34. if (!owner) owner = tmp;
  35. lockCount++;
  36. }
  37. // versucht das Objekt zu sperren
  38. bool Critical::tryLock()
  39. {
  40. if (lockCount > 0) return false;
  41. getThreadRegister()->lock();
  42. Thread* tmp = getThreadRegister()->zThread(CachedCurrentThread());
  43. if (tmp) tmp->addCriticalLock();
  44. getThreadRegister()->unlock();
  45. EnterCriticalSection(&cs);
  46. if (!owner) owner = tmp;
  47. lockCount++;
  48. return true;
  49. }
  50. // entsperrt das Objekt
  51. void Critical::unlock()
  52. {
  53. getThreadRegister()->lock();
  54. Thread* tmp = 0;
  55. if (getThreadRegister()->isThread(owner))
  56. {
  57. if (owner
  58. && GetThreadId(owner->getThreadHandle())
  59. != GetThreadId(CachedCurrentThread()))
  60. throw std::runtime_error("A Thread that does not own a Critical "
  61. "Object trys to unlock it");
  62. tmp = owner;
  63. }
  64. getThreadRegister()->unlock();
  65. if (!--lockCount) owner = 0;
  66. LeaveCriticalSection(&cs);
  67. getThreadRegister()->lock();
  68. if (tmp && getThreadRegister()->isThread(tmp)) tmp->removeCriticalLock();
  69. getThreadRegister()->unlock();
  70. }
  71. // gibt true zurück, wenn das Objekt gesperrt ist
  72. bool Critical::isLocked() const
  73. {
  74. return lockCount > 0;
  75. }
  76. // gibt einen Zeiger auf den Thread zurück, der das Objekt gesperrt hat
  77. const Thread* Critical::zOwner() const
  78. {
  79. return owner;
  80. }
  81. Synchronizer::Synchronizer()
  82. : numWaiting(0),
  83. skip(0)
  84. {}
  85. Synchronizer::~Synchronizer()
  86. {
  87. skip = 1;
  88. std::unique_lock<std::mutex> lk(mutex);
  89. if (numWaiting > 0)
  90. {
  91. lk.unlock();
  92. block.notify_all();
  93. }
  94. else
  95. lk.unlock();
  96. while (numWaiting > 0)
  97. Sleep(10);
  98. lk.lock();
  99. }
  100. bool Synchronizer::wait()
  101. {
  102. std::unique_lock<std::mutex> lk(mutex);
  103. if (skip) return false;
  104. numWaiting++;
  105. block.wait(lk);
  106. numWaiting--;
  107. return !skip;
  108. }
  109. bool Synchronizer::wait(int milisec)
  110. {
  111. std::unique_lock<std::mutex> lk(mutex);
  112. if (skip) return false;
  113. numWaiting++;
  114. std::cv_status status
  115. = block.wait_for(lk, std::chrono::milliseconds(milisec));
  116. numWaiting--;
  117. return !skip && status == std::cv_status::no_timeout;
  118. }
  119. void Synchronizer::notify()
  120. {
  121. block.notify_one();
  122. }
  123. void Synchronizer::notify(int amount)
  124. {
  125. while (amount--)
  126. block.notify_one();
  127. }
  128. void Synchronizer::notifyAll()
  129. {
  130. block.notify_all();
  131. }
  132. int Synchronizer::getNumberOfWaitingThreads() const
  133. {
  134. return numWaiting;
  135. }
  136. Framework::CriticalLock::CriticalLock(Critical* critical)
  137. {
  138. this->critical = critical;
  139. critical->lock();
  140. }
  141. Framework::CriticalLock::~CriticalLock()
  142. {
  143. critical->unlock();
  144. }