Thread View: pl.comp.lang.c
3 messages
3 total messages
Started by Szyk Cech
Wed, 11 Sep 2019 18:29
std::thread DESPERACKA PROŚBA O POMOC!!!
Author: Szyk Cech
Date: Wed, 11 Sep 2019 18:29
Date: Wed, 11 Sep 2019 18:29
148 lines
4302 bytes
4302 bytes
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
Re: std::thread DESPERACKA PROŚBA O POMOC!!!
Author: Wojciech Muła
Date: Wed, 11 Sep 2019 20:49
Date: Wed, 11 Sep 2019 20:49
25 lines
2354 bytes
2354 bytes
On Wednesday, September 11, 2019 at 8:29:21 PM UTC+2, Szyk Cech wrote: > Cześć! > > [Czego chcę] > Chcę napisać klasę realizującą semafor. > Chcę do niej napisać testy jednostkowe udowadniające jej proprawność. Dobra rada: zacznij od kompilowania swojego kodu z -fsanitize=thread. > [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ą. Nie masz wyścigu, tylko deadlock. Zakładasz, że wątki wykonają się w kolejności ich utworzenia. Zakładasz, że w chwili wykonania up(), notify_one będzie miała co obudzić. Zakładasz, że robisz join() na "wybudzonym" wątku. I to czasami nie jest spełnione. w.
Re: std::thread DESPERACKA PROŚBA O POMOC!!!
Author: M.M.
Date: Thu, 12 Sep 2019 12:09
Date: Thu, 12 Sep 2019 12:09
172 lines
6096 bytes
6096 bytes
On Wednesday, September 11, 2019 at 8:29:21 PM UTC+2, Szyk Cech wrote:
> 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
Hmmmm Nie wiem co program ma robić, z kodu, przepraszam, ale nie
chce mi się wnioskować. Co mogę ogólnie doradzić... W QT jest to
baaaardzo przejrzyście i intuicyjnie zrobione. Jest osobna klasa do
objęcia zapisów i osobna do odczytów.
https://doc.qt.io/qt-5/qreadlocker.html
https://doc.qt.io/qt-5/qwritelocker.html
https://doc.qt.io/qt-5/qreadwritelock.html
Jeśli musisz używać biblioteki standardowej, to napisz sobie takie
klasy. Podstawowa ich implementacja jest łatwa, sam pisałem kiedyś.
Potem zacznij od jednego lockera na cały program, odczyty obejmij
blokowaniem odczytów, a zapisy blokowaniem zapisów. Zadziała na
100%. Gdy będzie działało za wolno (czyt. gdy któryś z wątków
nie będzie obciążał na 100% rdzenia), to możesz pomyśleć o
zwiększeniu ilości lockerów w programie, ale trzeba to
zrobić z rozwagą: Dane które muszą zachować spójność w całym programie
muszą być objęte jednym i tym samym lockerem. Jeśli lockery są
zagnieżdżone, to kolejność wchodzenia do lockerów w każdej części
programu najlepiej jak jest taka sama.
Pozdrawiam
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads