🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

3 total messages Started by Szyk Cech Wed, 11 Sep 2019 18:29
std::thread DESPERACKA PROŚBA O POMOC!!!
#309922
Author: Szyk Cech
Date: Wed, 11 Sep 2019 18:29
148 lines
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!!!
#309923
Author: Wojciech Muła
Date: Wed, 11 Sep 2019 20:49
25 lines
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!!!
#309924
Author: M.M.
Date: Thu, 12 Sep 2019 12:09
172 lines
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