Template hier sinnvoll / möglich?



  • Hallo zusammen,

    ich aber gerade ein Problem, das für mich so aussieht als ob man es am besten mit einem Template löst. Allerdings bin ich mir nicht sicher, ob und wie das in diesem fall geht.
    Wenn es andere gute Lösungen ohne template gibt, wäre das natürlich auch ok.
    Also es geht dadrum, dass verschiedene Arten von Daten übers Netzwerk verschickt werden sollen.
    Ich mache dafür einen eigenen Thread, dem die Daten übergeben werden, diese werden erstmal in Queues gespeichert und dann von dem thread rausgeschickt (entweder sofort oder in regelmäßigen abständen oder so, da bin ich mir noch nicht sicher).

    Erstmal vorweg bevor code kommt:
    Ich habe das alles noch nicht getestet und wenn ich z.B. queue.poll verwende, dann ist mir dabei bewusst, dass das nicht unbedingt mit den klassen aus std so geht, mir geht es nur um den allgemeinen entwurf und nicht um die verwendung einer queue o.ä.

    Erstmal gibt es einige structs (hat erstmal nichts mit templates zu tun):

    struct A
    {
       int timestamp;
       double value;
    };
    
    struct B
    {
       int timestamp;
       char value[60];
    };
    ...
    

    Mir ist bewusst, dass ich noch keine Threadsynchronisation drin hab (siehe unten), das füge ich dann später ein, ist für den allgemeinen ansatz erstmal nicht wichtig.
    Jetzt will ich eine Funktion schreiben, die Daten von verschiedenen Typen übergeben bekommen kann und diese in verschiedenen Queues speichert, also erstmal ohne template:

    queue<A> aQueue;
    queue<B> bQueue;
    ....
    
    void submitData(A data)
    {
       aQueue.push_back(data);
    }
    void submitData(B data)
    {
       bQueue.push_back(data);
    }
    ...
    
    void run()
    {
       while(!aQueue.empty())
       {send(aQueue.poll();}
       while(!bQueue.empty())
       {send(bQueue.poll();}
       ...
    }
    

    Das oder ein ähnliches Verhalten will ich jetzt irgendwie "automatisieren".
    Wichtig ist es auch, dass bei der Empfängerseite das objekt in den richtigen typ konvertiert werden kann, dafür könnte ich z.B. eine id mitschicken, anhand der der typ übermittelt wird und dann je nach id den richtigen operanden für den streamingoperator verwenden.
    Wenn ihr dafür bessere Vorschläge habt, dann wäre das auch eine gute Hilfe.

    Mein erster Ansatz sieht wie folgt aus:

    class IDataTask
    {
    public:
    	virtual void send(ostream& os) = 0;
    };
    
    template<class T>
    class DataTask : public IDataTask
    {
    	T myData;
    public:
    	DataTask(T data) : myData(data){}
    	void send(ostream& os)
    	{
    		os << data;
    	}
    };
    
    Queue<IDataTask*> taskQueue;
    template<class T>
    void submitData(T data)
    {
        T* dataPtr = new T(data);
        taskQueue.push_back(dataPtr);
    }
    void run()
    {
       //am besten durch eine blockingqueue ersetzen...
       while(!taskQueue.isEmpty())
       {
           T* dataPtr = taskQueue.poll();
    	   send(*dataPtr, os);
    	   delete dataPtr;
       }
    }
    

    Was haltet ihr davon?
    Geht es vll einfacher / besser?
    Und wie krieg ich das hin, dass auf der Empfängerseite in die richtige Klasse konvertiert wird? Wie gesagt ist dazu mein ansatz, eine id mitzuschicken, die auf den typ gemappt wird und dann wird ein reinterpret_cast durchgeführt o.ä., nur das mapping von id auf typ müsste man dann ja hardcoden, oder?
    Und ich bin mir nicht sicher, ob das mit reinterpret_cast nicht evtl. gefährlich werden kann, z.B. wegen sowas wie little und big endian (obwohl QT, (das ich übrigens verwend) das fürs netzwerk afaik für einen handled).



  • Das Problem was du hast nennt sich im Allgemeinen Serialisierung.
    Falls deine Anwendung nicht zeitkritisch ist bzw. der Datenumfang im gemäßigten Rahmen ist, empfehle ich die Verwendung von Serialisierungsbibliotheken wie
    boost::serialisation oder die von google (Namen vergessen).

    Das spart viel Zeit und viele Probleme.



  • oder die von google (Namen vergessen).

    Google Protocol Buffers:
    http://code.google.com/p/protobuf/



  • Danke für die Tipps.

    Ich dachte immer mit serialisierung wäre eher gemeint zu bestimmen, wie ein objekt in bytes umgewandelt wird, also quasi die überladung der straemingoperatoren << und >>.
    Mein Problem hier ist ja eher die übergabe zum anderen Thread und zusätzlich dann die zuordnung zu typen beim deserialisieren (was dann doch wieder beim serialisieren landet).
    Am liebsten würde ich ohne eine zusatzbibliothek fürs serialisieren auskommen und was eigenes basteln.
    Überladen der streamingoperatoren ist kein problem, das hauptproblem liegt eher am herausfinden des datentyps beim empfangen, wozu ich mir bisher das mit der id überlegt hab, was aber noch nicht so super toll ist.

    Ich werd nochmal nen bischen selbst was versuchen, falls ich zu sehr verzweifle, verwende ich vll doch so ne bibliothek 🙂

    Falls ihr noch hilfen / tipps /etc. habt, immer her damit bitte 🙂


Anmelden zum Antworten