std::thread DESPERACKA PROŚBA O POMOC!!!

0

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

2

Mogę się mylić, ale czy przypadkiem nie zakładasz, że podniesienie semafora odblokuje Ci konkretny wątek? W pętli for, gdy i=10 podnosisz semafor i czekasz aż wykona się wątek o indeksie 5. Tymczasem w przypadku wielu zablokowanych wątków, standard nie określa który wątek zostanie odblokowany po użyciu condition_variable::notofy_one().

http://www.cplusplus.com/reference/condition_variable/condition_variable/notify_one/

0

Możesz mieć tak zwany spurious wakeup, gdy nie stosujesz żadnego warunku w momencie wywołania wait.
https://www.modernescpp.com/index.php/c-core-guidelines-be-aware-of-the-traps-of-condition-variables

A tutaj masz inną implementację semafora w C++11 używającą atomic variables zamiast condition variables .
https://stackoverflow.com/questions/42269611/non-blocking-semaphores-in-c11

1 użytkowników online, w tym zalogowanych: 0, gości: 1