2010-06-26 12 views
12

arbeite ich durch ein Kapitel über iPhone Audio und haben über einen Abschnitt von Code kommen, dass ich nicht Sinn machen kann:Warum verwenden Sie select() anstelle von sleep()?

while (aqc.playPtr < aqc.sampleLen) 
{ 
    select(NULL, NULL, NULL, NULL, 1.0); 
} 

(Full code sample is on pages 163-166). Von dem, was ich von dem Code verstehe, wird das Audio in einem anderen Thread verarbeitet und die While-Schleife ist nur da, um zu verhindern, dass der Haupt-Thread beendet wird, während Audio noch verarbeitet wird.

Was ich nicht verstehe ist, warum select() anstelle von sleep() verwendet wird.

Von dem, was ich gelesen habe select() wird verwendet, um Änderungen in I/O zu überwachen und es NULLs übergeben tut nichts sinnvolles. Ich habe den Code mit sleep() ausgeführt und es funktioniert wie erwartet. (Mein Wissen von niedrigem Niveau POSIX ist fast nicht vorhanden.)

+0

gruselig. Ich wusste nicht, dass die Leute immer noch diesen alten Trick benutzen. Und dies auf einer scheinbar neuen und glänzenden Architektur, wo viele andere Mittel zum "Schlafen" verfügbar sein sollten. Schade über den Programmierer/Schreiben eines solchen Codes. –

+5

@JensGustedt nicht so beängstigend wie ein 'double' als Parameter zu übergeben, wenn die Funktion einen ** Zeiger ** auf ein' struct timeval' erwartet – JeremyP

+0

@JensGustedt Dies ist eigentlich eine sehr sichere Art zu schlafen, weil sleep() nicht kann arbeiten z in einem Signalhandler. – LubosD

Antwort

17

Wählen Sie erlauben für genaue Sub Sekunde warten, und ist tragbarer als Schlaf. Es gibt andere Möglichkeiten zu warten, siehe this question.

Der Timeout-Parameter von select sollte jedoch kein float sein, sondern ein Zeiger auf struct timeval. Ich bin überrascht, dass der Code, den du zeigst, sogar kompiliert. Mehr: Dieser seltsamen bedingten Auswahl folgt ein bedingungsloser Schlaf (1). Sieht für mich sinnlos aus.

9

Mit select() mit NULLrfds, wfds und efds ist ein idiomatischer Weg von portably mit Subsekunden Auflösung schlafen.

+1

Aber ist 'Timeout' (das 5. Argument) nicht ein (möglicherweise NULL) Zeiger auf ein 'struct timeval'? –

+0

@Matthew ja, richtig. – ninjalj

+0

@MatthewFlaschen Und in diesem Fall würde es für immer schlafen. –

-1

Es gibt keinen Grund, es zu tun. Es gibt keinen Grund, jemals zu schlafen(). Man sollte immer mindestens eine Ereignis-Programm-Shutdown-Anfrage erwarten.

+0

Ich sehe nicht, was das mit irgendetwas zu tun hat. Eine Abschaltanforderung führt zu einem "SIGTERM", das von einem Signal-Handler, Standard oder anderweitig behandelt wird. –

+2

Das weder die Frage beantwortet, noch macht viel Sinn ... es gibt viele gute Gründe zu schlafen, vor allem auf Embedded-Plattformen (die Hälfte enthält das iPhone, denke ich) –

+0

Ich stimme mit Pavel ... es gibt fast nie einen Grund um Sleep() aufzurufen (außer möglicherweise als temporäre Debugging-Maßnahme). Jeder Thread, der in Sleep() blockiert wird, kann nicht sauber heruntergefahren werden, bis er aufwacht, was das Herunterfahren unnötig verlangsamt. (Wenn Sleep() als Antwort auf ein ankommendes Signal zurückkehrt, ist das ein Workaround dafür, aber das Mischen von Signalen und mehreren Threads ist ein eklatanter Haufen Würmer, den man am besten vermeiden sollte). Es ist besser, einen ereignisgesteuerten Ansatz zu verwenden und etwas zu blockieren, das durch ein ankommendes Ereignis, z. wählen(). –

4

Nun, Schlaf (3) kann durch Verwendung von Signalen implementiert werden. Es hängt von der Plattform ab.

Wenn Sie select (2) und poll (2) verwenden, wissen Sie, dass keine Signale beteiligt sind, was oft sehr nützlich ist. Wenn Sie z. B. den Alarm (2) verwenden, sollten Sie auch nicht den Ruhezustand (3) verwenden, da das "Mischen von Anrufen zu Alarm und Schlaf eine schlechte Idee ist".

Wählen und Abfragen geben Ihnen eine Millisekunden-Granularität beim Schlafen, aber der Schlaf hat nur eine Granularität in Sekunden.

3

Wenn Sie SIGALM-Signal in Ihrer Anwendung verwenden und (u)sleep Funktionen verwenden, wenn SIGALRM auftritt Programm sofort aus der Ruhezustandsfunktion zurückkehren, so ist der beste Weg zum Schlafen auf select Funktion zu warten.

struct timeval tv; 

tv.tv_sec = 1; 
tv.tv_usec = 1000; 

do 
{ 
    ret = select(1, NULL, NULL, NULL, &tv); 
} 
while((ret == -1)&&(errno == EINTR)); //select is interruped too 
+0

Wählt "TV" für die verstrichene Zeit? Wenn nicht, startet Ihre Warteschleife das gesamte Zeitintervall bei jedem EINTR-Ereignis neu. –

Verwandte Themen