Cześć!
[Czego chcę]
Chcę napisać klasę realizującą semafor.
Chcę do niej napisać testy jednostkowe udowadniające jej proprawność.
[Co ja robię]
Znalazłem w Internecie strony jakiejś instytucji naukowej na której
była klasa semafora i zainspirowany nią napisałem swoją wersję.
Oto te strony:
http://sandbox.mc.edu/~bennet/cs422b/notes/semaphore_h.html
http://sandbox.mc.edu/~bennet/cs422b/notes/semaphore_cpp.html
Jak widać klasa jest prosta jak drut. Jednak nie działa u mnie.
Mam wyścigi które zatrzymują aplikację testową.
Aplikacja działa w debugerze. Działa też gdy dodam jakieś linie:
cout << "message" << endl << flush;
Jednak nie działa gdy uruchamia się ją samodzielnie (ani w trybie debug
ani w trybie release).
Mój system to Linux KDE Neon (bazuje na Ubutnu 18.04 LTS).
Mój procesor to Intel Core Duo (z 2009 roku).
[Jak odtworzyć błąd]
Wklejam poniżej kod który jest kompletnym minimalnym przykładem.
Jest on w pełni automatyczny. Trzeba jedynie utworzyć 3 małe pliki,
nadać im uprawnienia wykonania i odpalić skrypt run.sh z lini komend.
Po 2-3 iteracjach u mnie wykonanie zamiera z nie znanego powodu.
Proszę o pomoc! Z góry dzięki i pozdro!
Szyk Cech
[Pliki]
BEGIN: run.sh
#!/bin/bash
./make.sh
lCounter=0
while [ 1 ]; do
lCounter=$[lCounter + 1]
echo "Run: $lCounter"
./semtest
done
END: run.sh
=============================================================
BEGIN: make.sh
#!/bin/bash
g++ -std=c++17 -pthread -O2 -s -DNDEBUG ./Main.cpp -o semtest
END: make.sh
=============================================================
BEGIN: Main.cpp
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <thread>
#include <vector>
#include <iostream>
using namespace std;
class Semaphore
{
public:
Semaphore(int aCounter);
public:
int value();
void up();
void down();
protected:
int mCounter;
std::mutex mAccessMutex;
std::condition_variable mWaitingCondition;
};
Semaphore::Semaphore(int aCounter)
: mCounter(aCounter)
{
}
int Semaphore::value()
{
return mCounter;
}
void Semaphore::down()
{
unique_lock lock(mAccessMutex);
--mCounter;
if(mCounter < 0)
mWaitingCondition.wait(lock);
}
void Semaphore::up()
{
unique_lock lock(mAccessMutex);
++mCounter;
if(mCounter <= 0)
mWaitingCondition.notify_one();
}
void SemTestThread(Semaphore* aSem)
{
aSem->down();
}
int main()
{
Semaphore lSem(5);
vector<thread> lArray;
lArray.resize(15);
for(unsigned long i(0); i < lArray.size(); ++i)
lArray[i] = thread(SemTestThread, &lSem);
bool lResult(true);
for(int i(0); i < 5; ++i)
lArray[i].join();
lResult = lResult && (lSem.value() == -10);
for(int i(10); i > 0; --i)
{
lSem.up();
lArray[15 - i].join();
lResult = lResult && (lSem.value() == -i + 1);
}
cout << "lResult: " << lResult << endl << flush;
// return EXIT_SUCCESS;
}
END: Main.cpp