PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : strukturen...| threads....



mithras
15-09-2002, 21:21
hab folgende struktur:





struct empfangen{
int sockfd;
int rw;
} *em;



D.h. ich habe einen Zeiger auf eine Instanz einer Struktur.
Die Struktur wurde außerhalb der main() bzw. außerhalb irgendeiner anderen Fkt. also global wie alle Strukturen definiert.
Nun kann ich ja an jeder Stelle im Programm über em->sockfd auf sockfd und em->rw auf rw zugreifen.
Das widerspricht doch aber eigentlich dem Konzept strukurierter Programmierung, in der versucht wird alles lokal innerhalb einer Fkt zu defenierern bzw. zu verwenden?!

Ich musste die obige Strukur definieren da ich mit Threads arbeite:




if(pthread_create(&t1, NULL, (void *)&getting, &arg) != 0) // Es wird neuer Thread aufgemacht,
{
perror("recv() failed");
fprintf(stderr, "Fehler bei Thread ......\n");
exit(0);
}



arg ist ein Argument das ich der Fkt. getting übergeben kann, ich kann jedoch nur ein argument übergeben, da ich aber mehrere Argumente übergeben möchte, muss ich mit einer Struktur arbeiten. Habe auch schon versucht das ganze folgerndermaßen zu machen, also mit einer Struktur ohne einen Zeiger auf die Instanz der Strukrur zu richten:




getting(struct em x);


struct empfangen{
int sockfd;
int rw;
} em;




Nun könnte ich ja z.B. der Fkt getting per empfangen(em) die Struktur übergeben, und in der Fkt mit x.sockfd und x.rw auf die Elemente zugreifen, wenn ich em aber per Thread einer Fkt. übergeben möchte, gibts eine fehlermeldung beim compelieren! Sodass ich das ganze mit opbier Struktur (mit Zeiger) und der Fkt. in pthread dann keine Argument übergebe, da ich ja aufgrund des Zeigers direkt auf die Elemente zugreifen kann!?

Kann mir jmd. helfen?

Syntax um einen Thread zu erstellen:



int pthread_create(pthread_t newthread, pthread_attr_t *attribute,
void *(*funktion)(void *), void *arg);


(von http://www.pronix.de/ckurs/ckurs211.html)

anda_skoa
15-09-2002, 22:21
Hi!

Mir ist nicht ganz klar, was jetzt das eigentliche Problem ist.

Zuerst liest es sich so, also möchtest du eine Alternative zu dem globalen Pointer, aber dann fragst du, ob du auch kein Argument übergeben kannst, weil du eh den globalen Pointer hast.

Ausgehend von der pthread_create Funktion steht fest, dass die Sigantur der Threadfunktion so aussehen muß:



void funktionsname(void* parameter)


Ob du den Parameter verwendest oder nicht, ist egal.
Wenn du ihn nicht verwenden willst, kannst du den Parameter in der Threadfunktion ja einfach ignorieren und bei pthread_create NULL an dessen Stelle schreiben.



void threadfunktion(void*)
{
}


// thread starter funktion
{
if (pthread_create(&tl, NULL, (void*)&threadfunktion, NULL) != 0)
}


Ciao,
_

mithras
15-09-2002, 23:10
Ok, meine Fragen/Probleme:

1. - Sind Strukturen mit Zeiger die global definert werden "schöner" Programmier-Stil? Oder kann man das irgendwie eleganter lösen?
2. - Kann ich der Funktion pthread, also wenn ich einen neuen Thread erstelle, der Funktion, die ich aufrufe mehrere Variablen übergeben ohne dass ich einen Zeiger auf eine Instanz einer Strukur richte. Ich denke dabei an eine "normale" Struktur ohne Zeiger?

hoffe ich hab mich verständlicher ausgedrückt.

anda_skoa
16-09-2002, 09:04
Ahh, so versteh ich es besser :)

ad 1)
Wie du schon selber erkannt hats ist es kein so guter Stil,
Manchmal ist es aber nur schwer umgänglich.

Wenn du eine feste Anzahl von Instanzen hast, kannst du sie auch in main() anlegen.

der Threaderzeugungsfunktion übergibts du dann einen Poiner auf die jeweilige Struktur.




struct Emfangen {
int socketfd;
int rw;
};

void erzeugeThread(struct Empfangen' em)
{
if (pthread_create(&tl, NULL, (void*) threadfunktion, em) != 0)
//...
}

int main()
{
struct Emfangen ems[100];

// erzeuge thread 34
erzeugeThread( &ems[34] );
}


Wenn die Anzahl der Threads nich limitiert ist, dann mußt du die struct dynamisch mit malloc erzeugen und in einen verkettet Liste geben (damit du aus dem Hautpprogramm Zugriff darafu hast)

ad 2)

Wie schon gesagt, ist die Threadfunktion auf ein Argument vom Typ void* limitiert.
D.h. es muß auf jedenfall ein Pointer sein.

Aber du kannst natürlich nur den Transfer mit Pointer machen.
(Dabei solltest du dir halt vor Augen halten, dass die Inhalte der Struktur kopiert werden müssen.
Alle gemeinsam veränderbaren Daten, müssen also als Pointer abgelegt sein)




struct Transfer {
struct Emfpangen em;
};

void threadfunktion(void* arg)
{
struct Emfpangen em;

if (arg != 0)
{
struct Emfangen* emp = (Emfangen*) arg;
em = emp->em;
free (emp);
}
}

void erzeugeThread(struct Empfangen em)
{
struct Empfangen* emp = malloc(sizeof(Empfangen);
emp->em = em;

if (pthread_create(&tl, NULL, (void*) empfangen, emp) != 0)
}


Allerdings ist das meiner Meinung nach ein ziemlicher Hack.

Ciao,
_

Sion
16-09-2002, 21:46
Original geschrieben von mithras
Ok, meine Fragen/Probleme:

1. - Sind Strukturen mit Zeiger die global definert werden "schöner" Programmier-Stil? Oder kann man das irgendwie eleganter lösen?
2. - Kann ich der Funktion pthread, also wenn ich einen neuen Thread erstelle, der Funktion, die ich aufrufe mehrere Variablen übergeben ohne dass ich einen Zeiger auf eine Instanz einer Strukur richte. Ich denke dabei an eine "normale" Struktur ohne Zeiger?

hoffe ich hab mich verständlicher ausgedrückt.
1. Global ist böse ;-)
2. In C kannst du als Parameter nur Zahlen oder Pointer (Zeiger) übergeben. Chars z.B. sind auch nur Zahlen, und Arrays werden (auch wenn manchmal nicht sofort ersichtlich) als Pointer übergeben.

zu dem Dynamik-Problem von mithras:
Du könntest ein array-Pointer von struct-Pointern mit malloc allocieren (Größe: Threadanzahl), die einzelnen Elemente davon werden dann in einer for-Schleife wieder mit malloc belegt (Größe: sizeof(struct Empfangen). Nun hast du für jeden der Thread eine eigene Struktur; der Thread bekommt beim Aufruf einen Pointer auf seine Struktur per Parameter "genannt", und kann darauf zugreifen.
Ist doch nicht sooo kompliziert ;-)

Gruß, Sion


========
Das könnte in etwa so aussehen:

void **structs;
int nThreads; // Anzahl Threads
int i;
structs = malloc(nThreads * sizeof (struct *Empfangen));

for (i=0; i < nThreads; i++)
structs[i] = malloc(sizeof(struct Empfangen));

for (i=0; i < nThreads; i++)
Erzeuge_Thread(structs[i]);

Die Fkt. Erzeuge_Thread mußt du nat. auch anpassen, daß sie Pointer entgegennimmt!