| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435 |
- #include "Critical.h"
- #include <iostream>
- #include <time.h>
- #include "Globals.h"
- #include "Thread.h"
- using namespace Framework;
- // Content of the Critical class from Critical.h
- // Konstructor
- Critical::Critical()
- {
- InitializeCriticalSection(&cs);
- lockCount = 0;
- }
- // Destructor
- Critical::~Critical()
- {
- DeleteCriticalSection(&cs);
- }
- // locks the object
- void Critical::lock()
- {
- currentThreadLockCount++;
- EnterCriticalSection(&cs);
- lockCount++;
- }
- // tries to lock the object
- bool Critical::tryLock()
- {
- if (lockCount > 0) return false;
- currentThreadLockCount++;
- EnterCriticalSection(&cs);
- lockCount++;
- return true;
- }
- // unlocks the object
- void Critical::unlock()
- {
- if (lockCount <= 0)
- {
- throw "A Thread tried to unlock a critical that was not locked before";
- }
- lockCount--;
- LeaveCriticalSection(&cs);
- currentThreadLockCount--;
- }
- // returns true if the object is locked
- bool Critical::isLocked() const
- {
- return lockCount > 0;
- }
- Synchronizer::Synchronizer()
- : numWaiting(0),
- skip(0)
- {}
- Synchronizer::~Synchronizer()
- {
- skip = 1;
- std::unique_lock<std::mutex> lk(mutex);
- if (numWaiting > 0)
- {
- lk.unlock();
- block.notify_all();
- }
- else
- lk.unlock();
- while (numWaiting > 0)
- Sleep(10);
- lk.lock();
- }
- bool Synchronizer::wait()
- {
- std::unique_lock<std::mutex> lk(mutex);
- if (skip) return false;
- numWaiting++;
- block.wait(lk);
- numWaiting--;
- return !skip;
- }
- bool Synchronizer::wait(int milisec)
- {
- std::unique_lock<std::mutex> lk(mutex);
- if (skip) return false;
- numWaiting++;
- std::cv_status status
- = block.wait_for(lk, std::chrono::milliseconds(milisec));
- numWaiting--;
- return !skip && status == std::cv_status::no_timeout;
- }
- void Synchronizer::notify()
- {
- block.notify_one();
- }
- void Synchronizer::notify(int amount)
- {
- while (amount--)
- block.notify_one();
- }
- void Synchronizer::notifyAll()
- {
- block.notify_all();
- }
- int Synchronizer::getNumberOfWaitingThreads() const
- {
- return numWaiting;
- }
- Framework::StackLock::StackLock(std::initializer_list<Lock*> locks)
- {
- this->locks = new Lock*[locks.size()];
- int i = 0;
- for (Lock* c : locks)
- {
- this->locks[i] = c;
- i++;
- }
- size = (int)locks.size();
- if (size > 0)
- {
- this->locks[0]->lock();
- int index = 1;
- while (index < size)
- {
- if (!this->locks[index]->tryLock())
- {
- for (int i = 0; i < index; i++)
- {
- this->locks[i]->unlock();
- }
- this->locks[index]->lock();
- this->locks[index]->unlock();
- this->locks[0]->lock();
- index = 1;
- }
- else
- index++;
- }
- }
- }
- Framework::StackLock::~StackLock()
- {
- for (int i = 0; i < size; i++)
- {
- locks[i]->unlock();
- }
- delete[] locks;
- }
- class Framework::InternalReadLock : public Lock
- {
- private:
- ReadWriteLock* rwLock;
- public:
- InternalReadLock(ReadWriteLock* rwLock)
- : rwLock(rwLock)
- {}
- virtual ~InternalReadLock() = default;
- void lock() override
- {
- rwLock->lockRead();
- }
- void unlock() override
- {
- rwLock->unlockRead();
- }
- bool tryLock() override
- {
- return rwLock->tryLockRead();
- }
- };
- class Framework::InternalWriteLock : public Lock
- {
- private:
- ReadWriteLock* rwLock;
- public:
- InternalWriteLock(ReadWriteLock* rwLock)
- : rwLock(rwLock)
- {}
- virtual ~InternalWriteLock() = default;
- void lock() override
- {
- rwLock->lockWrite();
- }
- void unlock() override
- {
- rwLock->unlockWrite();
- }
- bool tryLock() override
- {
- return rwLock->tryLockWrite();
- }
- };
- Framework::ReadWriteLock::ReadWriteLock(int initialMaxSize)
- : readerThreads(new int[initialMaxSize]),
- readCounters(new int[initialMaxSize]),
- maxSize(initialMaxSize),
- readerThreadCount(0),
- writerThread(0),
- writerCount(0),
- waitingReaders(0),
- waitingWriters(0),
- readLock(new InternalReadLock(this)),
- writeLock(new InternalWriteLock(this))
- {
- memset(readerThreads, 0, sizeof(int) * initialMaxSize);
- memset(readCounters, 0, sizeof(int) * initialMaxSize);
- }
- Framework::ReadWriteLock::~ReadWriteLock()
- {
- delete[] readerThreads;
- delete[] readCounters;
- delete readLock;
- delete writeLock;
- }
- void Framework::ReadWriteLock::lockRead()
- {
- cs.lock();
- while (writerCount > 0 && writerThread != currentThreadId)
- {
- waitingReaders++;
- cs.unlock();
- readerBlock.wait();
- cs.lock();
- waitingReaders--;
- }
- currentThreadLockCount++;
- int index = -1;
- for (int i = 0; i < readerThreadCount; i++)
- {
- if (readerThreads[i] == currentThreadId)
- {
- index = i;
- break;
- }
- }
- if (index == -1)
- {
- if (readerThreadCount == maxSize)
- {
- int* newReaderThreads = new int[maxSize * 2];
- int* newReadCounters = new int[maxSize * 2];
- for (int i = 0; i < maxSize; i++)
- {
- newReaderThreads[i] = readerThreads[i];
- newReadCounters[i] = readCounters[i];
- }
- delete[] readerThreads;
- delete[] readCounters;
- readerThreads = newReaderThreads;
- readCounters = newReadCounters;
- maxSize *= 2;
- }
- index = readerThreadCount++;
- readerThreads[index] = currentThreadId;
- }
- readCounters[index]++;
- cs.unlock();
- }
- void Framework::ReadWriteLock::lockWrite()
- {
- cs.lock();
- while (
- (writerCount > 0 && writerThread != currentThreadId)
- || (readerThreadCount > 0
- && (readerThreadCount != 1 || readerThreads[0] != currentThreadId)))
- {
- waitingWriters++;
- cs.unlock();
- writerBlock.wait();
- cs.lock();
- waitingWriters--;
- }
- currentThreadLockCount++;
- writerThread = currentThreadId;
- writerCount++;
- cs.unlock();
- }
- void Framework::ReadWriteLock::unlockRead()
- {
- cs.lock();
- int index = -1;
- for (int i = 0; i < readerThreadCount; i++)
- {
- if (readerThreads[i] == currentThreadId)
- {
- index = i;
- break;
- }
- }
- if (index == -1 || readCounters[index] == 0)
- {
- cs.unlock();
- throw "A Thread that does not hold a read lock tries to unlock it";
- }
- readCounters[index]--;
- if (readCounters[index] == 0)
- {
- readerThreads[index] = readerThreads[readerThreadCount - 1];
- readCounters[index] = readCounters[readerThreadCount - 1];
- readerThreadCount--;
- }
- if (readerThreadCount == 0 && waitingWriters > 0)
- {
- writerBlock.notify();
- }
- currentThreadLockCount--;
- cs.unlock();
- }
- void Framework::ReadWriteLock::unlockWrite()
- {
- cs.lock();
- if (writerThread != currentThreadId || writerCount == 0)
- {
- cs.unlock();
- throw "A Thread that does not hold the write lock tries to unlock it";
- }
- writerCount--;
- if (writerCount == 0)
- {
- if (waitingWriters > 0)
- {
- writerBlock.notify();
- }
- else if (waitingReaders > 0)
- {
- readerBlock.notify(waitingReaders);
- }
- }
- currentThreadLockCount--;
- cs.unlock();
- }
- bool Framework::ReadWriteLock::tryLockRead()
- {
- cs.lock();
- if (writerCount > 0 && writerThread != currentThreadId)
- {
- cs.unlock();
- return false;
- }
- currentThreadLockCount++;
- int index = -1;
- for (int i = 0; i < readerThreadCount; i++)
- {
- if (readerThreads[i] == currentThreadId)
- {
- index = i;
- break;
- }
- }
- if (index == -1)
- {
- if (readerThreadCount == maxSize)
- {
- int* newReaderThreads = new int[maxSize * 2];
- int* newReadCounters = new int[maxSize * 2];
- for (int i = 0; i < maxSize; i++)
- {
- newReaderThreads[i] = readerThreads[i];
- newReadCounters[i] = readCounters[i];
- }
- delete[] readerThreads;
- delete[] readCounters;
- readerThreads = newReaderThreads;
- readCounters = newReadCounters;
- maxSize *= 2;
- }
- index = readerThreadCount++;
- readerThreads[index] = currentThreadId;
- }
- readCounters[index]++;
- cs.unlock();
- return true;
- }
- bool Framework::ReadWriteLock::tryLockWrite()
- {
- cs.lock();
- if ((writerCount > 0 && writerThread != currentThreadId)
- || (readerThreadCount > 0
- && (readerThreadCount != 1 || readerThreads[0] != currentThreadId)))
- {
- cs.unlock();
- return false;
- }
- currentThreadLockCount++;
- writerThread = currentThreadId;
- writerCount++;
- cs.unlock();
- return true;
- }
- Lock& Framework::ReadWriteLock::getReadLock() const
- {
- return *readLock;
- }
- Lock& Framework::ReadWriteLock::getWriteLock() const
- {
- return *writeLock;
- }
|