Frage zu Vererbung und Memberzugriff



  • Die hauptidee zum Verbreiten der nachricht war, alles in ne Queue zu stopfen und der Empfänger soll sichs dann rausholen , wenn er es verarbeiten kann.

    (Ich weiß Threadsicher ist das auch (noch) nicht, aber das hätte ich schon irgendwie hingebastelt, da ja nur die Queue in beiden Threads zugriffe hat)



  • Ok, das mit der Nachrichtenerzeuger-Klasse hört sich ja gut an.

    Aber ich habe dazu noch Fragen.

    Also angenommen, ich habe eine Klasse, die Nachrichten erzeugen kann, und eine, die Nachrichten empfangen kann.

    Diese klassen werden also in einem Eigenen Thread laufen.
    Die Empfangsklasse muß ja nachrichten lagern können, da der Verarbeitende Thread ja womöglich nicht schnell genug ist. Also brauche ich nen Container.
    Aber beim Abholen aus dem Container weiß ich ja nicht mehr welche Klasse darin war. (bis auf die Kennung). Also muß die Empfängerklasse sowieso wieder anhand der Kennung die richtige Klasse herstellen und ich habe die Klassenerkennung wieder an 2 Stellen.

    Oder die NachrichtenEmpfangsklasse macht das auch noch. Dann muß ich ja aber für jeden Nachrichtentyp ne eigene get_Methode haben, da der Rückgabetyp ja eindeutig ist. Mache ich das nicht und benutze Tempaltes, muß die Verarbeitende Klasse wieder alles selber richtig herstellen und ich habe das selbe Problem.

    Mit welchem Design kann ich dan umgehen?



  • MisterX schrieb:

    ...Queue zu stopfen und der Empfänger soll sichs dann rausholen , wenn er es verarbeiten kann....Threadsicher...

    Das sind 3 weitere Anforderungen, denen Du mit geeigneten Mitteln zuleibe rücken solltest.
    Wenn Du eine Queue implementieren willst, solltest Du überlegen, eine Klasse/Struct/POD "Queuenachricht" anzulegen, die den Inhalt der Nachricht aufnimmt, und eine "Queueverwaltung", die entsprechend ein put()/get() anbietet.

    Außerdem klingt es so, als sollte es "Listener" geben, die sich bei der Queueverwaltung registrieren und von der bei Eintreffen einer "passenden" Nachricht angestoßen werden. So würde ich das jedenfalls implementerien.
    Die "Queueverwaltung" wäre dann der o.g. "Nachrichtenverwalter/-erzeuger" und die "Listener" wären dann die "Nachrichtenverarbeiter".

    Wenn das Ganze threadsicher sein soll, müsstes Du noch einiges mehr machen ... aber dazu gibt's dicke Bücher.

    Gruß,

    Simon2.



  • Hi,

    die Notwendigkeit eines Containers kommt allerdings nicht durch Multithreading rein, sondern die Anforderung "Queue" beinhaltet die bereits, weil "Queue" immer "asynchrone Verarbeitung" bedeutet .... und das bedeutet eben, dass Schreiber und Leser unabhängig voneinander sind. 😉

    Aber genug der Haarspalterei: Ja, Du brauchst einen Container. 😃
    Ich hätte einen Container von "QueueNachrichten" genommen. Die brauchen nicht viel zu können. Sie müssen nur wissen, wie lang sie sind und welche ihre "identifizierenden Bytes" sind.
    Du mußt fachlich entscheiden, wieviel Konsistenzcheck du in der Queue haben möchtest: Soll "alles" reingestellt werden können (auf die Gefahr hin, dass Nachrichten da drin vergammeln, ohne dass der "Absender" etwas davon merkt) ?
    Oder soll bereits beim Einstellen eine "später nicht verarbeitbare" Message abgelehnt werden ?
    Wenn Du mit "Listenern" arbeitest, kann der Queueverwalter dafür sorgen, dass nur "geputtet" werden kann, wofür jetzt/jemals ein Listener registriert wurde; aber das nimmt Dir die Chance, "vorab" zu füllen....
    Du kannst natürlich noch konfigurieren, welche Kennung prinzipiell eingestellt werden können ... aber das mußt Du dann auch immer konsistent halten.
    In Deinem Beispiel würde ich Nachrichtenempfang und -sendung in derselben Klasse ("Queueverwalter") implementieren, dann hast Du evtl. Abhängigkeiten immer zusammen.

    Ach ja: Kein C++-Standardcontainer kann von sich aus "asynchron arbeiten"; da brauchst Du anderes für. Schonmal bei streams umgeschaut ? (Man könnte ja z.B. auch ein eine Datei schreiben und lesen ... aber auch da muß man diverse Zugriffe serialisieren)...aber auch den std::Queue kannst Du Dir mal ansehen.

    Gruß,

    Simon2.



  • Ach ja: Kein C++-Standardcontainer kann von sich aus "asynchron arbeiten"; da brauchst Du anderes für. Schonmal bei streams umgeschaut ? (Man könnte ja z.B. auch ein eine Datei schreiben und lesen ... aber auch da muß man diverse Zugriffe serialisieren)...

    Ich habe da ma was gebastel,
    mein erster Versuch mit tempate und mein erster mit critical sections, also wahrscheinlich wieder von der Sorte "Abschreckendes Beispiel"

    #include <queue> 
    
    template<class T> class Queue_Thread_sicher
    
    {
    private:	queue<T> *q ;
    private:	CRITICAL_SECTION CriSect;
    
    public:	Queue_Thread_sicher() 
    	{
    		q= new queue<T>();
    		InitializeCriticalSection(&CriSect);
    	}
    
    public: ~Queue_Thread_sicher() 
    		{
    			DeleteCriticalSection(&CriSect);
    		}
    
    //liefern den Wert des letzten Elements .
    public: T back () 
    		{	 
    			EnterCriticalSection(&CriSect);
    				return q->back();
    			LeaveCriticalSection(&CriSect) ;	
    		}
    
    //gibt zurück, ob die queue leer ist
    public: bool empty()
    		{
    			EnterCriticalSection(&CriSect);
    				return q->empty();
    			LeaveCriticalSection(&CriSect);	
    
    		}
    
    //liefern den Wert des ersten Elements .
    public: T front () 
    		{
    			EnterCriticalSection(&CriSect);
    				return q->front();
    			LeaveCriticalSection(&CriSect) ;	
    		}
    
    //löscht das letzte element
    public: void pop () 
    		{	
    			EnterCriticalSection(&CriSect);
    				q->pop();
    			LeaveCriticalSection(&CriSect) ;	
    
    		}
    
    //Fügt ein Element hinzu
    public: void push (T t) 
    		{
    			EnterCriticalSection(&CriSect);
    				q->push(t);
    			LeaveCriticalSection(&CriSect) ;	
    		}
    
    //gibt die Größe an
    public:  float zize () 
    		{
    			EnterCriticalSection(&CriSect);
    				return q->size();
    			LeaveCriticalSection(&CriSect) ;	
    		}
    };
    

    Klappt das?



  • Hi,

    also ich will jetzt nicht in die ganze Breite der threadsafe-Programmierung eintauchen (bin ich auch nicht der Oberexperte drin).
    Nur soviel:
    - Mit CRITICAL_SECTIONs kenne ich mich nicht aus. Letztlich muß es auf Betriebssytemebene runter gehen. C++ bietet das nicht von sich aus.
    - Man muß darauf achten, dass man auch eine threadsafe-Version des Compilers hat.
    - Wenn Du alle Aufrufe über dieselbe "Ampel" (hier "CriSect") absicherst, unterbindest Du jegliche Parallelverarbeitung - was man selten braucht/will. Du mußt Du schon überlegen, was parallel laufen darf und was nicht (z.B. lesende/schreibende Zugriffe).
    - CriticalSections solltest Du via RAII (-> Technikbegriff nachschlagen) öffenen und schließen. Denk immer dran, dass auch exceptions fliegen können .. und zwar nahezu überall.
    - alle mit new (bzw. new[]) allozierten Ressourcen müssen mit delete (bzw. delete[]) freigegeben werden. => Eigentlich sehe ich hier gar keinen Bedarf für ein Heap-Objekt von queue...

    Kleine Anmerkung: Es ist in C++ unnötig und unüblich, jede Funktion
    a) erneut mit Zugriffsspezifikation auszustatten und
    b) inline zu definieren.

    Gruß,

    Simon2.



  • Hello! kbeaddb interesting kbeaddb site!


Anmelden zum Antworten