Ringpuffer



  • Hallo,
    habe folgendes Problem. Ich soll ein ein Testprogramm zur Ermittlung der Performance in einem GDI-Koordinator schreiben.
    Dazu soll ich auch Messwerte in einen Ringpuffer schreiben. Es existiert folgende Callback-Funktion an den Treiber:

    [void __stdcall IRReadChannelValues(
    MDAQCO_ThConnectionHandle hConnection,
    MDAQCO_ThDeviceComponentHandle hChannelOrGroup,
    const MDAQCO_TChannelStreamTransfer* poData)
    {
    /*
    typedef struct MDAQCO_TChannelStreamTransfer_tag
    {
    MDAQCO_TStreamTransferStatus m_oStatus; ///< Übertragungsstatus
    MDAQCO_TChannelStreamData m_oData; ///< Daten

    } MDAQCO_ALIGNMENT_SPEC MDAQCO_TChannelStreamTransfer;

    */

    unsigned long* ulValue=(unsigned long*)poData->m_oData.m_pData;

    for(unsigned long i=0;i<poData->m_oData.m_ulNumberOfDataBytes/4;i++)
    {
    printf("%ld ",*(ulValue));
    ulValue++;
    }

    }]

    ulValue speichert die von einem UDP-Programm übermittelten Daten. Diese sollen in den Ringpuffer geschrieben werden.
    Kann mir jemand erklären, wie ich am besten vorgehe?

    Vielen Dank im Vorraus.



  • /* noch unübersichtlicher bekommt man das auch nicht hin, oder?
    typedef struct MDAQCO_TChannelStreamTransfer_tag 
    { 
      MDAQCO_TStreamTransferStatus m_oStatus; ///< Übertragungsstatus 
      MDAQCO_TChannelStreamData m_oData; ///< Daten 
    } MDAQCO_ALIGNMENT_SPEC MDAQCO_TChannelStreamTransfer; 
    */ 
    
    void __stdcall IRReadChannelValues (MDAQCO_ThConnectionHandle hConnection, MDAQCO_ThDeviceComponentHandle hChannelOrGroup, const MDAQCO_TChannelStreamTransfer* poData)
      {
        unsigned long* ulValue=(unsigned long*)poData->m_oData.m_pData; //kein C++ !
    
        for (unsigned long i=0; i<poData->m_oData.m_ulNumberOfDataBytes/4; i++) 
          { 
            printf("%ld ",*(ulValue)); //KEIN C++ !
            ulValue++; 
          } 
      }
    

    wäre schon mal nen anfang gewesen ^^
    und guck dir mal namespaces an... das MDAQCO_ am Anfang nervt auch immer ein wenig ^^

    also geh entweder ins ANSI C Forum oder nimm std::cout, static_cast und vor allem ordentliche variablennamen!

    bb



  • Danke für die Kritik, hat mir jetzt nicht so wirklich weitergeholfen.
    Das is aber auch nicht meine Funktion.
    Ich will eigentlich nur wissen, wie ich nen Ringpuffer in C oder in C++ anlege.



  • SuperAdmin schrieb:

    Danke für die Kritik, hat mir jetzt nicht so wirklich weitergeholfen.
    Das is aber auch nicht meine Funktion.
    Ich will eigentlich nur wissen, wie ich nen Ringpuffer in C oder in C++ anlege.

    selber implementieren, oder einen fertigen irgendwo her besorgen.
    idR reicht aber ein std::list



  • Ich wäre sehr dankbar, wenn mir jemand vielleicht mal ein Quelltextbeispiel zum Thema geben könnte. Wär' ne coole Sache.



  • SuperAdmin schrieb:

    Ich wäre sehr dankbar, wenn mir jemand vielleicht mal ein Quelltextbeispiel zum Thema geben könnte. Wär' ne coole Sache.

    Benutz mal die Suchfunktion. Das hatten wir hier mal.



  • SuperAdmin schrieb:

    Ich wäre sehr dankbar, wenn mir jemand vielleicht mal ein Quelltextbeispiel zum Thema geben könnte. Wär' ne coole Sache.

    #include <deque>
    
    using namespace std;
    
    int main()
    {
    	const int SizeRingpuffer = 10;
    	int tvalue = 4;
    
    	deque<int> Ringpuffer(SizeRingpuffer, 0);
    
    	// Durch ein push_front(= Wert einfuegen) gefolgt von einem pop_back
    	// haelt der Ringpuffer seine konstante Laenge.
    	Ringpuffer.push_front(tvalue);
    	Ringpuffer.pop_back();
    
    	return 0;
    }
    

    😉



  • Hallo, ich bin's nochmal.
    Erstmal herzlichsten Dank für das kleine Beispiel, hat mir erstmal weitergeholfen.
    Noch 'ne kurze Frage. Klingt vielleicht blöd, bin aber noch Anfänger. 🙂
    Vereinfacht gesagt, ich will in einer for-Schleife ziemlich viele Daten einlesen.

    Einfaches Beispiel:

    for(i=0; i<=500; i++)
    {
         Value++;
    }
    

    Ein Ringpuffer bei konstanter Größe schmeißt doch die letzten Daten raus, wenn neue hinzugefügt werden, oder?
    Wie schaff ich es, den Puffer(der ja kleiner sein soll als die Anzahl der insgesamt abzuspeichernden Daten) in einer solchen Schleife zu befüllen, ohne dass ich Probleme mit dem Speicher bekomme ?

    (nicht lachen, wie gesagt, ANFÄNGER 🙂 )



  • Ich versteh deine Frage nicht so recht... Wie sollst du denn Probleme mit dem Speicher bekommen? Oo

    #include <deque> //hat nur leider kein reserver aber ich schätze mal, dass das trotzdem in Ordnung geht ^^
    
    template <size_t laenge>
      class meinRingpuffer_l
        {
          public:
    		  static size_t Limit ()                                     {return laenge;}
        };
    
    template <class T, size_t laenge = 500>
      class meinRingpuffer : public meinRingpuffer_l <500>
        {
          private:
            bool is_full;
            std::deque <T> container;
          public:
            meinRingpuffer () : is_full (false)
              {}
            meinRingpuffer (const meinRingpuffer <T> &rhs) : container (rhs.container), is_full (rhs.is_full)
              {}
            void add (const T &toadd)
              {
                if ((is_full) || (container.size () >= laenge))
                  {
                    is_full = true;
                    container.pop_front ();
                  }
                container.push_back (toadd);
              }
            const T& operator [] (const size_t i) const
              {
                return container.at (i);
              }
            //etc
        };
    
    #include <iostream>
    
    int main ()
    {
     meinRingpuffer <size_t, 10> eins;
     meinRingpuffer <size_t> zwei;
     meinRingpuffer <size_t> drei (zwei);
     for (size_t i (0); i <= 510; ++i)
      {
       drei.add (i);
      }
     for (size_t i (0); i < drei.Limit (); ++i)
      {
       std::cout << drei[i] << std::endl;
      }
    }
    

    so würd ichs anstellen

    bb



  • Vielen Dank, ich werd's mal ausprobieren !



  • Ich hab hier trotzdem noch'n Problem.
    Die Daten, die ich im Ringpuffer speichern will, kommen aus folgender callback-Funktion:

    void __stdcall IRReadChannelValues(
    									MDAQCO_ThConnectionHandle               hConnection,
    									MDAQCO_ThDeviceComponentHandle          hChannelOrGroup,
    									const MDAQCO_TChannelStreamTransfer*    poData)
    {
    	unsigned long* ulValue=(unsigned long*)poData->m_oData.m_pData;
    
    	for(unsigned long i=0;i<poData->m_oData.m_ulNumberOfDataBytes/4;i++)
    	{
    		printf("%ld ",*(ulValue));
    		ulValue++;
    		ulCounter++;
    		/*for(unsigned long i=0; i<poData->m_oData.m_ulNumberOfDataBytes/4; i++)
    		{
    			if(i<=1000)
    				deque1.push_back(*ulValue);
    			if(i>1000)
    			{
    				deque1.pop_front();
    				deque1.push_back(*ulValue);
    			}
    		}*/
    	}
    
    }
    

    Ne kurze Erklärung dazu. Im Hintergrund läuft ein UDP-Programm, das "Messdaten" in Form von Integerwerten liefert. In "poData" (out-Parameter) werden diese an die Funktion übergeben. Diese Werte werden wiederum an ulValue übergeben und bei Aufruf der Funktion in der Konsole entsprechend ausgegeben. Es können massig viele Werte sein, je nach Einstellung.
    MDAQCO_TChannelStreamTransfer* ist ein Zeiger auf eine Struktur, "m_oData.m_ulNumberOfDataBytes/4" speichert dann die Daten.
    Nun habe ich versucht, entsprechende Daten(ist das, was im Kommentar steht) in den Ringpuffer zu schreiben. Geb ich den allerdings aus, wird meine Begrenzung von 1000 Werten erheblich überschritten, genau genommen, läuft das Ganze ins Bodenlose. Zur Ausgabe nutze ich folgende Funktion:

    void printcontents(ULDEQUE deque)
    {
    	ULDEQUE::iterator pdeque1;
    	cout << "\nRingpuffer: \n";
    
    	for(pdeque1 = deque1.begin(); pdeque1 != deque1.end(); pdeque1++)
    	{
    		cout << *pdeque1 <<  " ";
    	}
    }
    

    (ULDEQUE ist ein globaler Ringpuffer-typedef, printcontents-Funktion rufe in der main() auf)

    Ich hoffe, das ihr was mit der Funktion und der Erklärung anfangen könnt und vielleicht ne Idee habt, wie man das Problemchen lösen kann.
    Für Vorschläge und Lösungen wäre ich sehr dankbar !



  • SuperAdmin schrieb:

    Ein Ringpuffer bei konstanter Größe schmeißt doch die letzten Daten raus, wenn neue hinzugefügt werden, oder?
    Wie schaff ich es, den Puffer(der ja kleiner sein soll als die Anzahl der insgesamt abzuspeichernden Daten) in einer solchen Schleife zu befüllen, ohne dass ich Probleme mit dem Speicher bekomme ?

    Mir sind Deine Anforderungen an den 'Ringpuffer ' nicht klar.
    Ein Ringpuffer mit konstanter Größe bekommt natürlich keine Probleme mit dem Speicher, weil seine Größe ja konstant ist!

    Was soll denn in Deiner Anwendung passieren, wenn der erste Messwert in den Rinpuffer geschrieben werden soll, der nicht mehr rein passt, also in diesem Fall das gewählte Limit von 1000 Werten übersteigt?

    Im Allgemeinen gibt es drei Möglichkeiten:
    - der älteste (also 1.) Wert wird gelöscht; bzw. überschrieben.
    - der Ringpuffer soll sich automatisch vergrößern
    - der schreibende Thread (also hier die Callbackfunktion) soll blockieren

    Gruß
    Werner


Anmelden zum Antworten