[C++] Asynchrone Methode

Online-Skater

Erfahrenes Mitglied
Hallo Tutorianer,

diesmal habe ich ein Problem mit asynchronen Methoden im Zusammenspiel mit Threads der boost library. Folgende Klasse ist gegeben:
C++:
class NetworkPlugin: public GenericPlugin
{
public:
 NetworkPlugin(DispatchUnit * dispatchUnit);
 virtual ~NetworkPlugin() {};
 virtual IODatap handleGetDataSync(const IODataType &type) = 0;
 virtual void handleSetData(const IODataType & type, IODatap data) = 0;
 void handleSetDataAsync(const IODataType & type, IODatap data, SetDataAsyncCallbackFunction callbackHandler);
 void handleSetDataSync(const IODataType & type, IODatap data);
private:
 static void helpSetDataAsync(SetDataAsyncHelperNetwork* sdah);
 boost::thread* tAsync;	///< Thread for handle data asynchronous
};
Möchte man nun asynchron Daten setzen, so ruft man handleSetDataAsync auf.
C++:
void NetworkPlugin::handleSetDataAsync(const IODataType & type, IODatap data, SetDataAsyncCallbackFunction callbackHandler)
{
  SetDataAsyncHelperNetwork* sdah = new SetDataAsyncHelperNetwork(this, type, data, callbackHandler);

  tAsync = new boost::thread(boost::bind(helpSetDataAsync, sdah));
}
Diese erstellt eine Struktur, welche die eigene Instanz (abgeleitet von NetworkPlugin) und die Paramter speichert. Diese wird mit der Methode helpSetDataAsync einem Thread übergeben, damit die Daten unabhängig vom aktuellen Thread gesetzt werden. Nun sollte die statische Methode helpSetDataAsync parallel gestartet werden.
C++:
void NetworkPlugin::helpSetDataAsync(SetDataAsyncHelperNetwork* sdah)
{
  try
  {
    sdah->instance->handleSetDataSync(sdah->type, sdah->data);
     if (sdah->callbackHandler)
    	 sdah->callbackHandler(sdah->type);
    delete sdah;
  }
  catch (AgentException agentException)
  {
    std::cerr<<"Exception in NetworkPlugin context ("<<agentException.reasonCode()<<"):"<< agentException.reasonText()<<"\n";
    exit(-agentException.reasonCode());
  }
}
Diese führt die synchrone Methode handleSetDataSync für das setzen von Daten aus und der Callbackhandler benachrichtigt das Plugin das die Daten gesetzt sind.
Die spannenden Fragen sind:
Es wird bei jedem Aufruf neuer Speicherplatz angefordert für den thread, und es wird nicht freigeräumt wenn der thread fertig ist. Wie kann man das lösen ? An welcher Stelle sollte ein join() ? Denn erst danach kann ich den Speicher freigeben !?
Kann man bei den boost_thread irgendwie ein Status abfragen ob der thread gestartet ist ähnlich wie bei pthread:
Code:
void NetworkPlugin::handleSetDataAsync(const IODataType & type, IODatap data, SetDataAsyncCallbackFunction callbackHandler)
{
  int ret;
  SetDataAsyncHelperNetwork* sdah = new SetDataAsyncHelperNetwork(this, type, data, callbackHandler);
  pthread_attr_t * attr = 0;
  void * arg = sdah;

  ret = pthread_create(&pthread, attr, NetworkPlugin::helpSetDataAsync, arg);
  if (ret != 0)
  {
     throw AgentException(AgentException::PluginRunError,
         "Cannot execute plugin thread to do setDataAsync");
   }
}

Wenn noch weitere Fragen sind oder ihr einen anderen Ansatz oder Vorschlag habt, asst mich nicht dumm sterben ;) Habe nur wenig Erfahrung mit boost::thread.

Mfg
 
Schade das keiner dazu beitragen kann :(
Ich habe mich nochmals bei der Dokumentation auf der boost Seite belesen. Habe nun die Methode folgendermaßen geändert:
C++:
void NetworkPlugin::handleSetDataAsync(const IODataType & type, IODatap data, SetDataAsyncCallbackFunction callbackHandler)
{
  try
  {
	  SetDataAsyncHelperNetwork* sdah = new SetDataAsyncHelperNetwork(this, type, data, callbackHandler);
	  boost::thread tAsync(boost::bind(helpSetDataAsync, sdah));
	  //alternative zu prüfen ob thread existiert = if (tAsync.joinable())
	  // no join cause the main thread should not be stopped
  }
  catch (boost::thread_resource_error &ex)
  {
	  throw AgentException(AgentException::PluginRunError, "Cannot execute plugin thread to do setDataAsync");
  }
}
Die Klasse NetworkPlugin hat nun keinen Zeiger auf boost::thread als Memvariable sondern der thread wird nun durch ein temporäres lokales Object erstellt. Nun habe ich kein Speicherleck mehr. Nachdem der Thread erstellt wurde, läuft er ja quasi parallel zum Hauptthread, d.h. die Methode handleSetDataAsync wird verlassen und der Destruktor von tAsync also dem Repräsentant des Threads aufgerufen. Das sollte aber nicht weiter schlimm sein denn es wird kein Zugriff auf den Thread gebraucht und er soll abgekoppelt vom Hauptthread (asynchron) arbeiten. Es wird also nicht der Hauptthread angehalten mittels join(), andernfalls wäre der vorgang nicht asynchron. Fall ihr noch bedenken seht lasst es mich wissen.

mfg ;)
 
Zurück