Shared Memory zwischen Threads

Alles rund um die Programmierung mit Qt
diddely
Beiträge: 49
Registriert: 9. Juli 2008 16:19

Shared Memory zwischen Threads

Beitrag von diddely »

Hi,


Ich habe ein Serial-Objekt, welches Daten von der RS232 Schnittstelle sammelt und sie in der eigenen Instanz (Qlist) abspeichert.

Ich habe einen Master-Thread, welcher diese Daten abholt indem er z.B. mit einem Signal vom Serial-Objekt signalisiert wird. (noch nicht sicher ob ich es so realisiere soll)
Ist Signal Slot bei dieser Anforderung ausreichend?


Diese Daten sollen, je nach Adressat, an den richtigen Worker-Thread weitergeleitet werden.
Daten sind = z.B. eine Struktur welche ein Byte-Array enthält.

Den Master-Thread gibt es nur einmal aber die Worker Threads wird es mehrfach geben. Die Zahl der worker-threads varieren zur Laufzeit.

Mein erster Gedanke war zuerst, dass ich dynamisch zwischen Master und dem jeweiligen Worker-Thread eine "Shared-Memory-Verbindung" herstelle.

1.)
Ist dies eine gute Vorgehensweise?
Gibt es noch eine andere Möglichkeit außer QtSharedMemory ?

2.)
Was noch in Frage kommen würde ist :
ich reserviere irgendwo Speicher, welchen ich mit z.B. Mutex schütze.

Wo sollte ich diesen Speicher reservieren?
Und wie sollten die Threads darauf zugreifen?

Evtl. da wo meine Thread-Instanzen erzeugt wurden? (im Parent)
So dass die threads über den this Ptr (vom Parent) auf den gem. Speicher zugreifen.

3.)
bezieht sich auf Frage 2)
Was ist wenn der Speicher nicht im Parent sondern ganz woanders liegen sollte.
Wäre ja unschön über mehrere Objekte den Pointer weiterzureichen.
Das kann man sicherlich noch besser realisieren.


Wie würdet ihr sowas realisieren?
Manchmal ist man gezwungen an Daten, die in anderen Instanzen liegen ranzukommen.
Hierbei kommt es vor, dass viele Objekte nicht auf der gleichen Ebene liegen sondern verschachtelt in anderen Objekten liegen.



Gruß

diddely
diddely
Beiträge: 49
Registriert: 9. Juli 2008 16:19

Beitrag von diddely »

Eine andere Frage, die ich mir gerade stelle bezieht sich auf das Master-Worker-Modell.

Ist es sinnvoll, die Worker-Threads im Master-Thread zu erzeugen?

Ich meine irgendwo im Forum gelesen zu haben, dass diese Vorgehensweise nicht zu empfehlen ist. Leider finde ich diesen Beitrag nicht mehr.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Threads brauchen kein QtSharedMemory - Threads teilen sich den gleichen Speicher.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Ist es sinnvoll, die Worker-Threads im Master-Thread zu erzeugen?
Wo willst du ansonsten deine Threads erzeugen?
diddely
Beiträge: 49
Registriert: 9. Juli 2008 16:19

Beitrag von diddely »

habe mehrere Thread-Instanzen,..

die dürften sich gegenseitig nicht stören.
diddely
Beiträge: 49
Registriert: 9. Juli 2008 16:19

Beitrag von diddely »

upsala hat geschrieben:
Ist es sinnvoll, die Worker-Threads im Master-Thread zu erzeugen?
Wo willst du ansonsten deine Threads erzeugen?
Eigentlich schon sooo aber...
Wie gesagt, habe hier im Forum irgendwo gelesen, dass man sowas nicht machen soll. Finde den Beitrag gerade nicht.
Suche mal gerade...
diddely
Beiträge: 49
Registriert: 9. Juli 2008 16:19

Beitrag von diddely »

Meine Aussage bezieht sich auf diesen Beitrag:
http://qtforum.de/forum/viewtopic.php?t ... ht=qthread
Imho ist es ein Designfehler wenn ein Thread einen weiteren erzeugt.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Damit meinte ich aber nur dass in einem QThread nicht unbedingt weitere QThreads erzeugt werden sollten. Da kommt man sonst nicht mehr raus. Mehr nicht.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
diddely
Beiträge: 49
Registriert: 9. Juli 2008 16:19

Beitrag von diddely »

stehe gerade auf dem Schlauch. :?:
Also ist es nicht empfehlenswert worker-threads im Master zu erzeugen?
Volker
Beiträge: 343
Registriert: 30. Juni 2005 05:27

Beitrag von Volker »

Mit Master Thread meint Christian denke ich den GUI Thread der Anwendung, der auf jeden Fall immer erzeugt wird. Und seine Aussage bezog sich auf neu erzeugte Threads die aus diesem Thread erzeugt wurden.
Bitte seid so nett und ändert den Titel von Beiträgen die gelöst wurden, auf [gelöst] Beitragstitel
diddely
Beiträge: 49
Registriert: 9. Juli 2008 16:19

Beitrag von diddely »

Ok,

meine Aussage bezieht sich nicht auf die GUI.
Wirklich nur das "Master-Worker-Modell".

Master, der die Arbeiten verteilt...die Arbeiter,..die die Arbeit verrichten.
Gut...ich werde die Worker dann im Master(Verteiler)-Thread erzeugen.

Wie soll ich am besten die Daten vom Master an die Worker übergeben?
Mir fällt auf die schnelle ein einfacher Funktionsaufruf ein:

Sowas hier:

Worker.getWork(data);

Der Master ruft die Method vom Worker auf um die Daten rüberzuschieben.
Oder gibt es da eine elegantere Vorgehensweise?
(Worker und Master sind unterschiedliche Klassen)
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

Oder gibt es da eine elegantere Vorgehensweise?
Signal/Slot?
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Funktionsaufruf oder ein Pointer. Der Funktionsaufruf ist imho besser da man ihn besser vor konkurrierenden Zugriff schützen kann (d.h. man kann es nicht irgendwo durch Zufall vergessen).

/edit: Signal-Slot ist auch eine Idee - aber eben Qt-spezifisch und Threadübergreifend erst seit Qt4 :)
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
diddely
Beiträge: 49
Registriert: 9. Juli 2008 16:19

Beitrag von diddely »

Ok danke!

Um es nochmal zu wiederholen:
Der Master-Thread würde die zu verteilenden Daten abholen, dann würde es sich den richtigen Thread aussuchen und mit einem worker.get_work(data) die Daten übergeben. (Oder wie empfohlen mit Signal/Slot)

Bei Signal/Slot müsste ich aber für jeden worker einen individuelles signal haben. worker0 kann nicht Daten bekommen, die für worker1 gedacht sind usw..
Von daher finde ich , dass es mit Funktionsaufrufen besser zu lösen ist.


Nochmal eine Überlegung zum Master-Thread:

Am besten stelle ich es mal so dar:
Objekt A = Parent
Obejkt B = Serial Objekt (sammelt Daten vom COM-Port)
Objekt C = Master(Verteiler)-Thread-Instanz

Objekt B und C werden im Parent A erzeugt.

Wenn mein Serial-Objekt B seine Daten gesammelt hat, schickt es ein Signal an Master-Thread.
Der muss nun die Daten von Objekt B abholen.
Hierfür habe ich den ptr von Objekt B über den Parent an Master-Thread weitergereicht, damit dieser an die gesammelten Daten von Objekt B rankommen kann.

Ich persönlich finde diese ptr-Weiterreichung unschön.
Ich denke mal ihr stimmt mir das zu????

Eine Möglichkeit wäre die Daten per Signal/Slot weiterzureichen.
Die Daten, die ich weiterreichen will sind eine Liste mit QbyteArrays.

Code: Alles auswählen

QList<QByteArray>
Superheftig
Beiträge: 63
Registriert: 6. September 2008 15:20

Beitrag von Superheftig »

Der einfachste Weg ist ne eigene Klasse zu erstellen, die die Daten verwalten. Diese Klasse machste als Singleton, dann kannste von überall drauf zugreifen. Innhalb der Klasse speicherste die daten private und machste ne get und set Methode die du per Mutex schützt. Fetig...Thread Save und du kommst von überall im Code dran.
Sieht dann so aus.

Class DataClass {

// Das ist der Singleton Teil der Klasse
public:
static Singleton * instance() // Pointer auf das Singleton Objekt
{
if( _instance == 0 ) _instance = new Singleton();
return _instance;
}
private:
Singleton() { /* ... */ } // Privater Konstruktor
static Singleton *_instance; // Das Singleton Objelt

// Der Teil ist für die Daten
public:
enqueue(DataType &newData) { // Neue Daten einfügen
MutexLocker locker(&mutex);
dataQueue.enqueu(newData);
}

DataType dequeue() { // Daten abarbeiten
MutexLocker locker(&mutex);
return dataQueue.dequeue();
}


private:
QQueuet<DataType> dataQueue;
QMutex mutex;

};

Wenn du die Daten jetzt von irgendwo im Code benutzten willst musst du nur die Klasse includen und dann DataClass::instance()->enqueue() bzw dequeue() aufrufen.
Ach und nicht das löschen des Singleton vergessen. Ganz am Ende wenn dein Programm terminiert einmal delete DataClass::instance() aufrufen.
Antworten