Hi Leute!
Ich bin bei meinem Projekt an einem Punkt wo ich erstmal nachfragen will nich das ich mich verenne.
Ich habe einen Threadpool (QList aus Threads).
Jeder Thread bekommt zu beginn seiner arbeit eine Anfrage von einem Netzwerkthread übergeben. nun muss der Thread entscheiden welches Modul er ansprechen muss (diese Module sollen in DLL's), soll dieses dynamisch laden und dann über das Modul seine Arbeit ausführen.
Was passiert wenn mehrere Threads nun Anfragen bekommen die auf das gleiche Modul gehen? blockieren die Threads dann oder hat jeder Thread wirklich "seine" instanz des Moduls und kann ohne einfluss der anderen damit Arbeiten?
Multithreading und externe DLL's
Mist, ich hab angenommen, dass jedesmal, wenn ich ein QPluginLoader-Objekt erstelle, ich bei instance() auch ein neues Objekt bekomme. Aber dem ist nicht so. Es ist immer das selbe!
Demnach kannst du nicht mehrere verschiedene Objekte in deinen Threads aus dem Plugin laden, und somit hast du (wenn jedes dieser Plugin eigene Memberdaten hat) auch ein Problem...
Ich leider auch, denn bisher hab ich angenommen, das wäre kein Problem, und bisher hat auch alles geklappt, weil ich immer nur EINE Instanz eines Plugins geladen hatte. Da muss ich echt schaun dass ich das hinkrieg, muss man wohl selber machen mit QLibrary...
Ich schau mal wie das der PluginLoader anstellt.
Grüße
Franz
Demnach kannst du nicht mehrere verschiedene Objekte in deinen Threads aus dem Plugin laden, und somit hast du (wenn jedes dieser Plugin eigene Memberdaten hat) auch ein Problem...
Ich leider auch, denn bisher hab ich angenommen, das wäre kein Problem, und bisher hat auch alles geklappt, weil ich immer nur EINE Instanz eines Plugins geladen hatte. Da muss ich echt schaun dass ich das hinkrieg, muss man wohl selber machen mit QLibrary...
Ich schau mal wie das der PluginLoader anstellt.
Grüße
Franz
Das ist doch nicht wirklich ein Problem... Entweder darf es die gleiche Instanz sein, dann muss diese Klasse einfach MT-tauglich implementiert worden sein (Zugriff auf Members mittels Mutexe serialisieren).
Oder es darf nicht die gleiche Instanz sein, dann liefert die Library halt einfach eine (MT-taugliche) Factory, welche soviele Instanzen produziert, wie benoetigt (z.B. pro Thread) werden...
Uebrigens erzeugt die QApplication die bei instance() zurueckgegebene Instanz schon beim Programmstart (falls da der Pluginpfad schon bekannt ist und das Plugin auch schon existiert). Dies kann schoen mit einer qDebug()-Ausgabe im CTor des Plugins beobachtet werden.
Oder es darf nicht die gleiche Instanz sein, dann liefert die Library halt einfach eine (MT-taugliche) Factory, welche soviele Instanzen produziert, wie benoetigt (z.B. pro Thread) werden...
Code: Alles auswählen
MyFactory *f = qobject_cast<MyFactory*>(loader->instance());
Q_ASSERT(f);
MyModule *m = f->produce();
m->........
-
thereapman
- Beiträge: 36
- Registriert: 6. Juni 2007 15:39
@solarix:
Versuche grad deinen Code zu verstehen.
Seh ich das richtig so das in der DLL eine Factory/Klasse implementiert ist und die beim aufruf von produce einfach intern mit new die eigentliche modulklasse neu anlegt und die addresse zurückgibt?
Wenn ja wie ist das mit der Aufräumerei? kann ich wenn ich das vom produce() angelegte Object in meinem Thread habe von dort aus einfach ein delete auf das Object machen?
Versuche grad deinen Code zu verstehen.
Seh ich das richtig so das in der DLL eine Factory/Klasse implementiert ist und die beim aufruf von produce einfach intern mit new die eigentliche modulklasse neu anlegt und die addresse zurückgibt?
Wenn ja wie ist das mit der Aufräumerei? kann ich wenn ich das vom produce() angelegte Object in meinem Thread habe von dort aus einfach ein delete auf das Object machen?
gute Frage.. IMHO spielt es unter Unix-Systemen keine Rolle (*.so), jedoch unter Windows (*.dll) schon (getrennter Heap). Ich meinte am sichersten ist, entweder im Plugin
a) neben der "produce()"-Methode auch noch eine "destroy()" anzubieten, oder (falls die Factory spaeter nicht mehr vorhanden ist)
b) dem produziertem Objekt eine "destroy()" ("delete this;") hinzu zu fuegen, so dass die im Plugin erstellte Instanz nicht mit "delete obj", sondern mit "obj->destroy()" zerstoert wird... am besten mit privatem Destruktor, so dass "delete obj;" gar nicht mehr moeglich ist...)
a) neben der "produce()"-Methode auch noch eine "destroy()" anzubieten, oder (falls die Factory spaeter nicht mehr vorhanden ist)
b) dem produziertem Objekt eine "destroy()" ("delete this;") hinzu zu fuegen, so dass die im Plugin erstellte Instanz nicht mit "delete obj", sondern mit "obj->destroy()" zerstoert wird... am besten mit privatem Destruktor, so dass "delete obj;" gar nicht mehr moeglich ist...)
Richtig Module, also im Sinne von Plugins zu implementieren, ist gar ned so ohne !
Ich kenn mich mit QLibrary und QPlugin oder wie die heissen ned so aus, ich mach es immer QT frei. (wir haben mehrere Projecte die unsere Plugins anziehen, und ned jedes verwendet die QT).
Wichtig ist zu wissen, unter windows, das eine dll immer nur einmal geladen werden kann. Das betrifft natuerlich nur den Code. nen Loadlibrary laed das ding, und der code wird in deinem Prozess eingeblendet an ner gewissen adresse. Fuer ihre globalen und lokalen variablen wird der dll ein eigener "Stack" zugewiesen, aus dem verfuegbaren Speicher des Prozesses . Das heisst, das globale variablen aus ner dll im selben prozess immer die gleichen sind.
Aber , trotz das die dll nur einmal geladen wird, bekommt ein anderer prozess fuer die gleiche dll natuerlich einen anderen Stack aus seinem eigenen speicherbereich. Das heisst, bei unterschiedlichen prozessen, sind auch die variablen unnerschiedlich.
Weiterhin ist wichtig zu wissen, das man new und delete, bzw alloc und free im selben module nur aufrufen sollte ...
also new in der dll, delete in der exe oder ner anderen dll sollt krachen. Mit paar tricks kann man das verhindern, iss aber auesserst unsauber.
Meistens baut man dann plugins so , das die dll eine Pluginfactory global beim laden / einblenden des Speichers in den Prozess erzeugt. das kann man statisch im stack der dll mit ner globalen variable, oder dynamsich beim DllMain (beim DllFree wieder zerstoren oder automatische objecte nehmen) mit dem zeiger allerdings auch wieder global, erledigen. eine exportierte dll funktion gibt nen zeiger auf die Factory dann nach aussen.
Von der Factory kann man dann meisten Instanzen von den Plugins erzeugen mittels einer Create Funktion und einer zugehörigen release version.
Ciao ...
Ich kenn mich mit QLibrary und QPlugin oder wie die heissen ned so aus, ich mach es immer QT frei. (wir haben mehrere Projecte die unsere Plugins anziehen, und ned jedes verwendet die QT).
Wichtig ist zu wissen, unter windows, das eine dll immer nur einmal geladen werden kann. Das betrifft natuerlich nur den Code. nen Loadlibrary laed das ding, und der code wird in deinem Prozess eingeblendet an ner gewissen adresse. Fuer ihre globalen und lokalen variablen wird der dll ein eigener "Stack" zugewiesen, aus dem verfuegbaren Speicher des Prozesses . Das heisst, das globale variablen aus ner dll im selben prozess immer die gleichen sind.
Aber , trotz das die dll nur einmal geladen wird, bekommt ein anderer prozess fuer die gleiche dll natuerlich einen anderen Stack aus seinem eigenen speicherbereich. Das heisst, bei unterschiedlichen prozessen, sind auch die variablen unnerschiedlich.
Weiterhin ist wichtig zu wissen, das man new und delete, bzw alloc und free im selben module nur aufrufen sollte ...
also new in der dll, delete in der exe oder ner anderen dll sollt krachen. Mit paar tricks kann man das verhindern, iss aber auesserst unsauber.
Meistens baut man dann plugins so , das die dll eine Pluginfactory global beim laden / einblenden des Speichers in den Prozess erzeugt. das kann man statisch im stack der dll mit ner globalen variable, oder dynamsich beim DllMain (beim DllFree wieder zerstoren oder automatische objecte nehmen) mit dem zeiger allerdings auch wieder global, erledigen. eine exportierte dll funktion gibt nen zeiger auf die Factory dann nach aussen.
Von der Factory kann man dann meisten Instanzen von den Plugins erzeugen mittels einer Create Funktion und einer zugehörigen release version.
Ciao ...