Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (GNU/Linux, *NIX, *BSD und Co) » mutex lock durch for-schleife??

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
18.06.2019, 13:16 Uhr
herrmann_wst



Hallo zusammen,
ich stehe vor einem kleinen Problem.
Ich habe ein Programm das Daten dauerhaft über eine Schnittstelle senden soll. Heist ich habe eine Funktion mit der ich die zu sendenden Werte updaten kann und das Senden selbst läuft asyncron.

In meiner main lege ich nun einen Vector an, welchen ich dann an meine "update" (in meinem Programm send()) übergebe.

Diese send() Funktion kopiert den Inhalt in einen Anderen Vector. Da auf diesen zweiten Vector auch auf aus dem Thread (pthread) zugegriffen wird, ist dieser Kopiervorgang durch einen mutex lock geschützt.

füttere Ich den Vector folgendermaßen mit daten, funktioniert alles einwandfrei:

C++:
data.push_back(1);
data.push_back(1);
data.push_back(1);
data.push_back(1);
data.push_back(1);



ist aber halt unschön. Daher folgende Idee:

C++:
for(uint8_t j = 0; j < 5; j++)
    {
        data.push_back(1);
    }



ABER:
mit dieser Lösung bleibt das Programm beim Aufruf von send(), genauer beim mutex lock, stehen. Der Inhalt und die größe des Vectors stimmen aber. Sieht so aus als wäre der mutex dann schon gelockt.
Zu Testzwecken habe ich auch den Thread erstmal nicht gestartet, gleiches Problem. Da der Thread nicht läuft kann der mutex ja aber eigentlich garnicht gelockt sein. Raceconditions dürften da ja ausgeschlossen sein. Oder habe ich da was falsch verstanden?

Das gesamte Programm sieht folgendermaßen aus:

Main:

C++:
#include<iostream>
#include<vector>
#include"./PN512/sender.h"

int main(void)
{

    PN512Sender snd;
    //snd.start(); //start Thread, vorerst auskommentiert
    std::vector<uint8_t> data;
    uint8_t counter = 0; //ja, ich weis dass der im laufe des Programms überläuft. Das ist aber so gewollt und funktioniert auch

    //nicht funktionierender Teil:
    for(uint8_t j = 0; j < 5; j++)
    {
        data.push_back(1);
    }

    /*
    //Funktionierender Teil:
    data.push_back(1);
    data.push_back(1);
    data.push_back(1);
    data.push_back(1);
    data.push_back(1);
    */



    while(1)
    {
        data[0] = counter;
        counter++;
        snd.send(&data[0], data.size());
        sleep(1);
    }
}



Klasse PN512Sender (erst header, dann .cpp):

C++:
#include<pthread.h>
#include"./pn512.h"
#include<vector>
#include<unistd.h>

class PN512Sender
{
    private:
    std::vector<uint8_t> sendBuffer;
    pthread_mutex_t lock;
    bool run;
    pthread_t snd_thd;
    PN512 pn;

    public:
    PN512Sender();
    void start(void);
    void stop(void);
    void send(uint8_t *dataToSend, uint8_t dataSize);
    void clearSendBuffer();

    private:
    static void * sendLoopEntry(void * self);
    void* sendLoop(void);

};





C++:
#include "sender.h"

PN512Sender::PN512Sender()
{
    pn.PCD_Init();
    run = false;
}

void PN512Sender::start(void)
{
    run = true;
    pthread_create(&snd_thd, NULL, sendLoopEntry, this);
}

void PN512Sender::stop(void)
{
    run = false;
    pthread_join(snd_thd, NULL);
}

void PN512Sender::send(uint8_t *dataToSend, uint8_t dataSize)
{
    if(dataSize > 0 && dataToSend != NULL)
    {

        std::cout <<"send"<<std::endl;
        pthread_mutex_lock(&lock);  //programm bleibt hier stehen
        std::cout <<"send2"<<std::endl;

        this->sendBuffer.clear();

        sendBuffer.push_back(dataSize + 2);
        for(uint8_t i = 0; i < dataSize; i++)
            this->sendBuffer.push_back(dataToSend[i]);
        sendBuffer.push_back(dataSize + 2);

        pthread_mutex_unlock(&lock);
    }
}


void PN512Sender::clearSendBuffer()
{
    pthread_mutex_lock(&lock);
    this->sendBuffer.clear();
    pthread_mutex_unlock(&lock);
}

void * PN512Sender::sendLoopEntry(void * self)
{
    return static_cast<PN512Sender*>(self)->sendLoop();
}

void* PN512Sender::sendLoop(void)
{
    while(run)
    {
        //clear FIFO
        pn.PCD_WriteRegister(pn.FIFOLevelReg, 0x80); //pn wird ausschließlich vom Thread genutzt, daher kein mutex

        pthread_mutex_lock(&lock);
        if(sendBuffer.size() > 0)
        {
            pn.PCD_WriteRegister(pn.FIFODataReg, sendBuffer.size(), &sendBuffer[0]);
            pthread_mutex_unlock(&lock);
        }
        else
        {
            pthread_mutex_unlock(&lock);
            continue;
        }

        //start Transmission
        pn.PCD_WriteRegister(pn.CommandReg, pn.PCD_Transmit);
        //wait for Transmission to complete
        while(pn.PCD_ReadRegister(pn.CommandReg) == pn.PCD_Transmit);

    }
    pthread_exit(NULL);
}




Kann mir jemand erklären was ich da falsch mache?

MfG
herrmann_wst

Dieser Post wurde am 18.06.2019 um 13:21 Uhr von herrmann_wst editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
18.06.2019, 17:05 Uhr
ao

(Operator)


Du initialisierst den Mutex nicht. Ein Mutex muss IMMER initialisiert werden.

Dass dein Programm in der einen Variante (scheinbar!) läuft, ist vermutlich blanker Zufall.

Lies nach bei pthread_mutex_init, wie das geht. Der Konstruktor von PN512Sender wäre der passende Ort, um das zu machen.

Außerdem ein dringender Rat: Bei allen Systemaufrufen (mutex_lock, mutex_unlock, thread_create usw.) den Returnvalue abholen und ein perror machen, wenn selbiger nicht OK ist. Ich wette, das hätte dir schon weiterhelfen können (EINVAL z.B. als Hinweis darauf, dass &lock kein initialisierter Mutex ist).

Und noch ein Hinweis: Seit C++11 enthält auch die C++-Standardbibliothek Multithreading- und Synchronisations-Klassen. std::thread, std::mutex usw. Wenn du kannst, benutz das und nicht diese alte pthread-lib. Du hast damit diesen ganzen Initialisierungs-Ärger nicht.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
18.06.2019, 21:42 Uhr
FloSoft
Medialer Over-Flow
(Administrator)



Zitat:

Und noch ein Hinweis: Seit C++11 enthält auch die C++-Standardbibliothek Multithreading- und Synchronisations-Klassen. std::thread, std::mutex usw. Wenn du kannst, benutz das und nicht diese alte pthread-lib. Du hast damit diesen ganzen Initialisierungs-Ärger nicht.



Oder wenn C++11 nicht zur Verfügung steht, nimm boost.
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
24.06.2019, 14:22 Uhr
herrmann_wst



Hi,
sorry für die späte Antwort und danke für die Hinweise. Hab das init jetzt in den Konstruktor der Sender Klasse gepackt....jetzt lässt sich der mutex garnicht mehr locken. Sowohl mit als auch ohne for...



Zitat von FloSoft:

Zitat:

Und noch ein Hinweis: Seit C++11 enthält auch die C++-Standardbibliothek Multithreading- und Synchronisations-Klassen. std::thread, std::mutex usw. Wenn du kannst, benutz das und nicht diese alte pthread-lib. Du hast damit diesen ganzen Initialisierungs-Ärger nicht.



Oder wenn C++11 nicht zur Verfügung steht, nimm boost.


Hatte ich mir auch schon angeschaut...aber der Prof bei dem ich das abgeben muss ist ein totaler pthread fan, daher die entscheidung zu pthread.

Mfg
herrmann_wst
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
24.06.2019, 15:58 Uhr
ao

(Operator)


An dem for kanns aber nicht liegen. Und wenns scheinbar doch so ist, dann ist das Zufall. Du hast irgendwo anders einen Fehler. Kriegst du auffällige Errorcodes? Beim Initialisieren oder beim Benutzen des Mutex?

Ohne Code kann man leider nicht nachvollziehen, was du gemacht hast.

"aber der Prof bei dem ich das abgeben muss ist ein totaler pthread fan ..."
Und der hat euch nicht gezeigt, wie man mit pthread-Mutexen umgeht?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
24.06.2019, 16:48 Uhr
herrmann_wst



Hallo nochmal,
habs inzwischen hinbekommen. Das ursprüngliche Problem war der fehlende Init Aufruf. Danach nochmal ein Clean & Build und das Problem war verschwunden .

"Und der hat euch nicht gezeigt, wie man mit pthread-Mutexen umgeht"
doch hat er, ist aber schon ein bisschen her...

MfG
herrmann_wst
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (GNU/Linux, *NIX, *BSD und Co) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: