Critical.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. #include "Critical.h"
  2. #include <iostream>
  3. #include <time.h>
  4. #include "Globals.h"
  5. #include "Thread.h"
  6. using namespace Framework;
  7. // Content of the Critical class from Critical.h
  8. // Konstructor
  9. Critical::Critical()
  10. {
  11. InitializeCriticalSection(&cs);
  12. lockCount = 0;
  13. }
  14. // Destructor
  15. Critical::~Critical()
  16. {
  17. DeleteCriticalSection(&cs);
  18. }
  19. // locks the object
  20. void Critical::lock()
  21. {
  22. currentThreadLockCount++;
  23. EnterCriticalSection(&cs);
  24. lockCount++;
  25. }
  26. // tries to lock the object
  27. bool Critical::tryLock()
  28. {
  29. if (lockCount > 0) return false;
  30. currentThreadLockCount++;
  31. EnterCriticalSection(&cs);
  32. lockCount++;
  33. return true;
  34. }
  35. // unlocks the object
  36. void Critical::unlock()
  37. {
  38. if (lockCount <= 0)
  39. {
  40. throw "A Thread tried to unlock a critical that was not locked before";
  41. }
  42. lockCount--;
  43. LeaveCriticalSection(&cs);
  44. currentThreadLockCount--;
  45. }
  46. // returns true if the object is locked
  47. bool Critical::isLocked() const
  48. {
  49. return lockCount > 0;
  50. }
  51. Synchronizer::Synchronizer()
  52. : numWaiting(0),
  53. skip(0)
  54. {}
  55. Synchronizer::~Synchronizer()
  56. {
  57. skip = 1;
  58. std::unique_lock<std::mutex> lk(mutex);
  59. if (numWaiting > 0)
  60. {
  61. lk.unlock();
  62. block.notify_all();
  63. }
  64. else
  65. lk.unlock();
  66. while (numWaiting > 0)
  67. Sleep(10);
  68. lk.lock();
  69. }
  70. bool Synchronizer::wait()
  71. {
  72. std::unique_lock<std::mutex> lk(mutex);
  73. if (skip) return false;
  74. numWaiting++;
  75. block.wait(lk);
  76. numWaiting--;
  77. return !skip;
  78. }
  79. bool Synchronizer::wait(int milisec)
  80. {
  81. std::unique_lock<std::mutex> lk(mutex);
  82. if (skip) return false;
  83. numWaiting++;
  84. std::cv_status status
  85. = block.wait_for(lk, std::chrono::milliseconds(milisec));
  86. numWaiting--;
  87. return !skip && status == std::cv_status::no_timeout;
  88. }
  89. void Synchronizer::notify()
  90. {
  91. block.notify_one();
  92. }
  93. void Synchronizer::notify(int amount)
  94. {
  95. while (amount--)
  96. block.notify_one();
  97. }
  98. void Synchronizer::notifyAll()
  99. {
  100. block.notify_all();
  101. }
  102. int Synchronizer::getNumberOfWaitingThreads() const
  103. {
  104. return numWaiting;
  105. }
  106. Framework::StackLock::StackLock(std::initializer_list<Lock*> locks)
  107. {
  108. this->locks = new Lock*[locks.size()];
  109. int i = 0;
  110. for (Lock* c : locks)
  111. {
  112. this->locks[i] = c;
  113. i++;
  114. }
  115. size = (int)locks.size();
  116. if (size > 0)
  117. {
  118. this->locks[0]->lock();
  119. int index = 1;
  120. while (index < size)
  121. {
  122. if (!this->locks[index]->tryLock())
  123. {
  124. for (int i = 0; i < index; i++)
  125. {
  126. this->locks[i]->unlock();
  127. }
  128. this->locks[index]->lock();
  129. this->locks[index]->unlock();
  130. this->locks[0]->lock();
  131. index = 1;
  132. }
  133. else
  134. index++;
  135. }
  136. }
  137. }
  138. Framework::StackLock::~StackLock()
  139. {
  140. for (int i = 0; i < size; i++)
  141. {
  142. locks[i]->unlock();
  143. }
  144. delete[] locks;
  145. }
  146. class Framework::InternalReadLock : public Lock
  147. {
  148. private:
  149. ReadWriteLock* rwLock;
  150. public:
  151. InternalReadLock(ReadWriteLock* rwLock)
  152. : rwLock(rwLock)
  153. {}
  154. virtual ~InternalReadLock() = default;
  155. void lock() override
  156. {
  157. rwLock->lockRead();
  158. }
  159. void unlock() override
  160. {
  161. rwLock->unlockRead();
  162. }
  163. bool tryLock() override
  164. {
  165. return rwLock->tryLockRead();
  166. }
  167. };
  168. class Framework::InternalWriteLock : public Lock
  169. {
  170. private:
  171. ReadWriteLock* rwLock;
  172. public:
  173. InternalWriteLock(ReadWriteLock* rwLock)
  174. : rwLock(rwLock)
  175. {}
  176. virtual ~InternalWriteLock() = default;
  177. void lock() override
  178. {
  179. rwLock->lockWrite();
  180. }
  181. void unlock() override
  182. {
  183. rwLock->unlockWrite();
  184. }
  185. bool tryLock() override
  186. {
  187. return rwLock->tryLockWrite();
  188. }
  189. };
  190. Framework::ReadWriteLock::ReadWriteLock(int initialMaxSize)
  191. : readerThreads(new int[initialMaxSize]),
  192. readCounters(new int[initialMaxSize]),
  193. maxSize(initialMaxSize),
  194. readerThreadCount(0),
  195. writerThread(0),
  196. writerCount(0),
  197. waitingReaders(0),
  198. waitingWriters(0),
  199. readLock(new InternalReadLock(this)),
  200. writeLock(new InternalWriteLock(this))
  201. {
  202. memset(readerThreads, 0, sizeof(int) * initialMaxSize);
  203. memset(readCounters, 0, sizeof(int) * initialMaxSize);
  204. }
  205. Framework::ReadWriteLock::~ReadWriteLock()
  206. {
  207. delete[] readerThreads;
  208. delete[] readCounters;
  209. delete readLock;
  210. delete writeLock;
  211. }
  212. void Framework::ReadWriteLock::lockRead()
  213. {
  214. cs.lock();
  215. while (writerCount > 0 && writerThread != currentThreadId)
  216. {
  217. waitingReaders++;
  218. cs.unlock();
  219. readerBlock.wait();
  220. cs.lock();
  221. waitingReaders--;
  222. }
  223. currentThreadLockCount++;
  224. int index = -1;
  225. for (int i = 0; i < readerThreadCount; i++)
  226. {
  227. if (readerThreads[i] == currentThreadId)
  228. {
  229. index = i;
  230. break;
  231. }
  232. }
  233. if (index == -1)
  234. {
  235. if (readerThreadCount == maxSize)
  236. {
  237. int* newReaderThreads = new int[maxSize * 2];
  238. int* newReadCounters = new int[maxSize * 2];
  239. for (int i = 0; i < maxSize; i++)
  240. {
  241. newReaderThreads[i] = readerThreads[i];
  242. newReadCounters[i] = readCounters[i];
  243. }
  244. delete[] readerThreads;
  245. delete[] readCounters;
  246. readerThreads = newReaderThreads;
  247. readCounters = newReadCounters;
  248. maxSize *= 2;
  249. }
  250. index = readerThreadCount++;
  251. readerThreads[index] = currentThreadId;
  252. }
  253. readCounters[index]++;
  254. cs.unlock();
  255. }
  256. void Framework::ReadWriteLock::lockWrite()
  257. {
  258. cs.lock();
  259. while (
  260. (writerCount > 0 && writerThread != currentThreadId)
  261. || (readerThreadCount > 0
  262. && (readerThreadCount != 1 || readerThreads[0] != currentThreadId)))
  263. {
  264. waitingWriters++;
  265. cs.unlock();
  266. writerBlock.wait();
  267. cs.lock();
  268. waitingWriters--;
  269. }
  270. currentThreadLockCount++;
  271. writerThread = currentThreadId;
  272. writerCount++;
  273. cs.unlock();
  274. }
  275. void Framework::ReadWriteLock::unlockRead()
  276. {
  277. cs.lock();
  278. int index = -1;
  279. for (int i = 0; i < readerThreadCount; i++)
  280. {
  281. if (readerThreads[i] == currentThreadId)
  282. {
  283. index = i;
  284. break;
  285. }
  286. }
  287. if (index == -1 || readCounters[index] == 0)
  288. {
  289. cs.unlock();
  290. throw "A Thread that does not hold a read lock tries to unlock it";
  291. }
  292. readCounters[index]--;
  293. if (readCounters[index] == 0)
  294. {
  295. readerThreads[index] = readerThreads[readerThreadCount - 1];
  296. readCounters[index] = readCounters[readerThreadCount - 1];
  297. readerThreadCount--;
  298. }
  299. if (readerThreadCount == 0 && waitingWriters > 0)
  300. {
  301. writerBlock.notify();
  302. }
  303. currentThreadLockCount--;
  304. cs.unlock();
  305. }
  306. void Framework::ReadWriteLock::unlockWrite()
  307. {
  308. cs.lock();
  309. if (writerThread != currentThreadId || writerCount == 0)
  310. {
  311. cs.unlock();
  312. throw "A Thread that does not hold the write lock tries to unlock it";
  313. }
  314. writerCount--;
  315. if (writerCount == 0)
  316. {
  317. if (waitingWriters > 0)
  318. {
  319. writerBlock.notify();
  320. }
  321. else if (waitingReaders > 0)
  322. {
  323. readerBlock.notify(waitingReaders);
  324. }
  325. }
  326. currentThreadLockCount--;
  327. cs.unlock();
  328. }
  329. bool Framework::ReadWriteLock::tryLockRead()
  330. {
  331. cs.lock();
  332. if (writerCount > 0 && writerThread != currentThreadId)
  333. {
  334. cs.unlock();
  335. return false;
  336. }
  337. currentThreadLockCount++;
  338. int index = -1;
  339. for (int i = 0; i < readerThreadCount; i++)
  340. {
  341. if (readerThreads[i] == currentThreadId)
  342. {
  343. index = i;
  344. break;
  345. }
  346. }
  347. if (index == -1)
  348. {
  349. if (readerThreadCount == maxSize)
  350. {
  351. int* newReaderThreads = new int[maxSize * 2];
  352. int* newReadCounters = new int[maxSize * 2];
  353. for (int i = 0; i < maxSize; i++)
  354. {
  355. newReaderThreads[i] = readerThreads[i];
  356. newReadCounters[i] = readCounters[i];
  357. }
  358. delete[] readerThreads;
  359. delete[] readCounters;
  360. readerThreads = newReaderThreads;
  361. readCounters = newReadCounters;
  362. maxSize *= 2;
  363. }
  364. index = readerThreadCount++;
  365. readerThreads[index] = currentThreadId;
  366. }
  367. readCounters[index]++;
  368. cs.unlock();
  369. return true;
  370. }
  371. bool Framework::ReadWriteLock::tryLockWrite()
  372. {
  373. cs.lock();
  374. if ((writerCount > 0 && writerThread != currentThreadId)
  375. || (readerThreadCount > 0
  376. && (readerThreadCount != 1 || readerThreads[0] != currentThreadId)))
  377. {
  378. cs.unlock();
  379. return false;
  380. }
  381. currentThreadLockCount++;
  382. writerThread = currentThreadId;
  383. writerCount++;
  384. cs.unlock();
  385. return true;
  386. }
  387. Lock& Framework::ReadWriteLock::getReadLock() const
  388. {
  389. return *readLock;
  390. }
  391. Lock& Framework::ReadWriteLock::getWriteLock() const
  392. {
  393. return *writeLock;
  394. }
  395. int Framework::ReadWriteLock::getReadThreadCount() const
  396. {
  397. return readerThreadCount;
  398. }
  399. bool Framework::ReadWriteLock::isWriteLocked() const
  400. {
  401. return writerCount > 0;
  402. }
  403. int Framework::ReadWriteLock::getReadThread(int index) const
  404. {
  405. if (index < 0 || index >= readerThreadCount)
  406. {
  407. throw "Index out of bounds";
  408. }
  409. return readerThreads[index];
  410. }
  411. int Framework::ReadWriteLock::getWriteLockThread() const
  412. {
  413. return writerThread;
  414. }
  415. int Framework::ReadWriteLock::getWriteLockCount() const
  416. {
  417. return writerCount;
  418. }
  419. int Framework::ReadWriteLock::getReadLockCount(int threadId) const
  420. {
  421. for (int i = 0; i < readerThreadCount; i++)
  422. {
  423. if (readerThreads[i] == threadId)
  424. {
  425. return readCounters[i];
  426. }
  427. }
  428. return 0;
  429. }