PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Schleife nach bestimmter Zeitspanne verlassen



onkeltom
26-04-2005, 06:54
Ich möchte eine Schleife, in der eine Eingabe stattfinden muss beenden wenn eine Minute lang keine Eigabe erfolgt ist.
Hat da jemand einen Tip für mich?

peschmae
26-04-2005, 08:41
Gute Frage. Die normalen Lesefunktionen haben ja keinen Timeout den man angeben könnte.

Um welche Sprache gehts überhaupt?

Hab da für C etwas gefunden:
http://ns1.livepenguin.com/pipermail/vox-tech/2003-April/005188.html

MfG Peschmä

onkeltom
26-04-2005, 08:47
Sorry, hatte ich vergessen, aber C war schon die richtige Sprache.
Hatte allerdings gehofft die Lösung sei etwas einfacher als in dem Link dargestellt. Trotzdem schon mal danke für den Tip.

DukePyrolator
27-04-2005, 05:18
Eine ganz einfache Lösung wäre folgende:



time_t endtime;

endtime = time(NULL) + 60;

[schleifenanfang]

if (endtime <= time(NULL) ) break;

[schleifenende]



time(NULL) liefert die aktuelle Zeit in Sekunden zurück, wir addieren noch 60 Sekunden dazu. Das ist dann die Zeit, zu welcher die Schleife abgebrochen werden soll. In der Schleife selbst überprüfen wir einfach, ob die aktuelle Zeit gleich oder später der "endzeit" ist.

peschmae
27-04-2005, 06:16
Und wo wird hier die Eingabe gemacht? Das ist ja das Problem. Nicht die 60 Sekunden oder so zu warten.

MfG Peschmä

onkeltom
27-04-2005, 06:58
genau das ist das Problem.
Wenn ich nämlich auf die Eingabe warte wird die Zeit erst nach der Eingabe wieder abgefragt.

DukePyrolator
27-04-2005, 09:33
huch, da hab ich wohl die Problemstellung nicht richtig gelesen. Sorry. :o

Ich hab mich jetzt hauptsächlich darauf konzentriert, die Schleife nach einer bestimmten Zeitspanne abzubrechen.

hmm, das ist ja jetzt auf einmal viel komplizierter geworden als ich dachte. :)

michael.sprick
27-04-2005, 10:13
Hi,

in Perl würde ich sowas mit Threads lösen... gibts das denn nicht in C?

almoeli
27-04-2005, 14:14
Hi,

naja Threads sind dafür wohl etwas heftig. In C und mit der GNU C Lib kann man sehr einfach mit den zur Verfügung gestellten Funktionen für timer machen:



#include <sys/time.h>
#include <signal.h>

void sig_alrm(__attribute__((unused)) int dummy)
{
}

int read_with_timeout(int fd, char *buffer, int size)
{
struct itimerval ival;
struct sigaction myaction;
size_t len;

/* Activate timer */
myaction.sa_handler = sig_alrm;
myaction.sa_flags = SA_ONESHOT | SA_NOMASK;
sigaction(SIGALRM, &myaction, NULL);

memset(&ival, 0, sizeof(struct itimerval));
/* Hier die Anzahl der Sekunden fuer den Timeout eintragen */
ival.it_value.tv_sec = 60;

if (setitimer(ITIMER_REAL, &ival, NULL) != 0) {
fprintf(stderr, "Could not start the timer\n");
return -1;
}

len = read(fd, bufpos, size);

/* Release timer */
memset(&ival, 0, sizeof(struct itimerval));
ival.it_value.tv_sec = 0;

if (setitimer(ITIMER_REAL, &ival, NULL) != 0) {
fprintf(stderr, "Could not delete the timer\n");
return -1;
}

myaction.sa_handler = SIG_DFL;
myaction.sa_flags = 0;
sigaction(SIGALRM, &myaction, NULL);

return len;
}


Das read im Code funktioniert mit einen Filedescriptor. Es kann aber auch jederzeit durch fread usw. ersetzt werden. Das funktioniert dann genauso.

Der Code macht nichts anderes, als während des read einen Timeout aufzuziehen. Läuft dieser ab, so wird der read durch Signal SIGALRM abgebrochen (und liefert -EINTR also errno).

Hoffe das hilft dir weiter

almoeli

peschmae
27-04-2005, 17:33
Ah, das sieht schon mal recht nett aus. :)

MfG Peschmä

7.e.Q
09-05-2005, 11:03
Ums kurz zu sagen: es reicht, wenn du vor dem read() einen Signal Handler für SIGALRM mit dem Flag SA_ONESHOT definierst, dann mit setitimer() einen Timer aufziehst und nach dem read() den Signal Handler wieder zurück biegst.

Ich glaub, den Handler zurück biegen ist gar nicht notwendig, weil das durch das SA_ONESHOT Flag schon abgedeckt ist.