2010-06-26 8 views
12

estoy trabajando a través de un capítulo sobre el iPhone de audio y he encontrado una sección de código que no puedo dar sentido a:¿Por qué usar select() en lugar de sleep()?

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

(Full code sample is on pages 163-166). Por lo que entiendo del código, el audio se está procesando en otro hilo y el ciclo while está ahí para evitar que el hilo principal termine mientras el audio todavía se está procesando.

Lo que no entiendo es por qué select() se está utilizando en lugar de sleep().

De lo que he leído select() se usa para controlar los cambios en E/S y pasarlo NULLs no hace nada significativo. He ejecutado el código usando sleep() y funciona como se esperaba. (Mi conocimiento de bajo nivel POSIX es casi inexistente.)

+0

scary. No sabía que la gente todavía usa ese viejo truco. Y esto en una arquitectura aparentemente nueva y brillante donde muchos otros medios para 'dormir' deberían estar disponibles. vergüenza en el programador/escribir de tal código. –

+5

@JensGustedt no es tan aterrador como pasar un 'doble' como parámetro cuando la función espera un ** puntero ** a una' struct timeval' – JeremyP

+0

@JensGustedt Esta es una forma muy segura de dormir, porque el sueño() puede no trabajo, por ejemplo en un controlador de señal. – LubosD

Respuesta

17

Seleccione permitir una espera de segundo segundo precisa, y es más portátil que dormir. Hay otras formas de esperar, vea this question.

Pero el parámetro de tiempo de espera de select no debe ser un flotante sino un puntero a struct timeval. Me sorprende que el código que muestres incluso compile. Más: esta extraña selección condicional es seguida por un sueño incondicional (1). Me parece inútil

9

Usando select() con NULLrfds, wfds y efds es una forma idiomática de forma portátil dormir con resolución por debajo del segundo.

+1

¿Pero no se supone que 'timeout' (el 5º argumento) es un puntero (posiblemente NULL) para una' struct timeval'? –

+0

@Matthew sí, correcto. – ninjalj

+0

@MatthewFlaschen Y en ese caso dormiría para siempre. –

-1

No hay ninguna razón para hacerlo. No hay razón alguna para dormir() tampoco. Siempre se debe esperar al menos un evento: solicitud de cierre del programa.

+0

No veo qué tiene eso que ver con nada. Una solicitud de apagado causará un 'SIGTERM' que es manejado por un manejador de señal, predeterminado o no. –

+2

Eso no responde a la pregunta, ni tiene mucho sentido ... hay muchas buenas razones para dormir, especialmente en plataformas integradas (que a medias incluye el iPhone, supongo) –

+0

Estoy de acuerdo con Pavel ... casi nunca hay una razón llamar a Sleep() (excepto posiblemente como una medida de depuración temporal). Cualquier hilo que esté bloqueado en Sleep() no se puede cerrar limpiamente hasta que se despierte, lo que hace que el apagado sea innecesariamente lento. (Tener el retorno de Sleep() en respuesta a una señal entrante es una solución para eso, pero mezclar señales y múltiples hilos es una bolsa de gusanos desagradable que es mejor evitar). Es mejor usar un enfoque basado en eventos y bloquear algo que pueda ser desbloqueado por un evento entrante, p. seleccionar(). –

4

Bueno, el sueño (3) puede implementarse mediante el uso de señales. Depende de la plataforma.

Cuando usa select (2) y poll (2), sabe que no se verán señales, lo que a menudo es muy útil. Por ejemplo, si está usando la alarma (2), tampoco debería usar sleep (3), porque "mezclar llamadas para alarmar y dormir es una mala idea" (según la página del manual)

Además, select y poll le dan una granularidad de milisegundos cuando duerme, pero el sueño solo tiene una granularidad en términos de segundos.

3

Cuando utiliza la señal SIGALM en su aplicación y usa las funciones (u)sleep, cuando se produce SIGALRM el programa vuelve inmediatamente de la función de reposo, por lo que la mejor manera de dormir es esperar la función select.

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

¿Selecciona ajustar 'tv' por el tiempo transcurrido? De lo contrario, su ciclo de espera se reiniciará durante todo el intervalo de tiempo en cada aparición de 'EINTR'. –

Cuestiones relacionadas