Thread anhalten

07/04/2010 - 10:03 von Curtis Newton | Report spam
Hallo,

ich nutze pthreads.

Die thread-Funktion sieht grob so aus:
void thrfnc(void *)
{
do
{
...
}
while(!_stop)
}

Nun möchte ich den Thread ab und zu kurz anhalten. Ich mache das bisher
so, dass ich außerhalb des Threads ein flag setze und dieses im Thread
abfrage (innerhalb der do-while-Schleife):

while(_halt)
{
usleep(100000);
}

Finde ich unschön. Wie macht man das schön? Ich habe mich schon ein
bißchen und phtread_cond_wait eingelesen, scheinbar aber noch nicht ganz
verstanden. Und ich will ja nicht jedes mal auf ein Signal warten,
sondern den Thread nur anhalten können.


C.
Bye
 

Lesen sie die antworten

#1 Jan Seiffert
07/04/2010 - 10:44 | Warnen spam
Curtis Newton schrieb:
Hallo,

ich nutze pthreads.

Die thread-Funktion sieht grob so aus:
void thrfnc(void *)
{
do
{
...
}
while(!_stop)
}

Nun möchte ich den Thread ab und zu kurz anhalten. Ich mache das bisher
so, dass ich außerhalb des Threads ein flag setze und dieses im Thread
abfrage (innerhalb der do-while-Schleife):

while(_halt)
{
usleep(100000);
}

Finde ich unschön. Wie macht man das schön? Ich habe mich schon ein
bißchen und phtread_cond_wait eingelesen, scheinbar aber noch nicht ganz
verstanden. Und ich will ja nicht jedes mal auf ein Signal warten,
sondern den Thread nur anhalten können.




Das mit dem "gewaltsam anhalten" ist schon immer ein Problem gewesen, aus dem
gleichen Grund warum ein Thread cancel boese ist:
Der Thread koennte in dem moment eine wichtige Rescource halten.
(Weniger verklausoliert: Wenn du einen Thread cancelst oder suspendest waerend
er einen Lock haelt, hast du ein Problem).

Du wirst also den Thread weiterhin kooperativ dazu ueberreden muessen, doch
bitte mal grad pause zu machen.
Der condional hilft dir den Thread wieder zu starten, ohne dieses polling/sleep
gedoehnse. (Mit weiteren conditionals koenntest du auch signalisieren wenn der
Thread endlich erkannt hat er soll pause machen usw.. Aber auf Lockinversion
achten!)

Beispiel (stark verkuerzt):

mutex flag_lock;
cond flag_cond;
bool halt;

void thrfnc(void *)
{
do
{
/* insert heavy work here */
...
mutex_lock(flag_lock);
if(halt)
cond_wait(flag_cond, flag_mutex);
mutex_unlock(flag_lock);
} while(!stop)
}

void send_sleep(void)
{
mutex_lock(flag_lock);
halt = true;
mutex_unlock(flag_lock);
}

void send_wakeup(void)
{
mutex_lock(flag_lock);
halt = false;
cond_broadcast(flag_cond);
mutex_unlock(flag_lock);
}


Ich weiss nicht ob das geht:

mutex flag_lock;
cond flag_cond;
bool halt;

void thrfnc(void *)
{
do
{
/* insert heavy work here */
...
mutex_lock(flag_lock);
if(halt) {
/* waeke alle, die darauf warten das wir schlafen */
cond_broadcast(flag_cond);
cond_wait(flag_cond, flag_mutex);
}
mutex_unlock(flag_lock);
} while(!stop)
}

void send_sleep(void)
{
mutex_lock(flag_lock);
halt = true;
/* warte bis thread schlaeft, oder nicht mehr schlafen soll */
cond_wait(flag_cond, flag_lock);
mutex_unlock(flag_lock);
}

void send_wakeup(void)
{
mutex_lock(flag_lock);
halt = false;
cond_broadcast(flag_cond); /* waeke alle */
mutex_unlock(flag_lock);
}

Achtung, im zusammenspiel zwischen 2 threads sollte das gehen (minus Bugs), wenn
mehr threads den einen Thread steuern wollen enthaelt obiger code ein paar nette
ueberraschungen (wer waeckt wen wann...).


C.


Gruss
Jan

class WindowsVista extends WindowsXP implements nothing
{}

Ähnliche fragen