[Programación] Re: [Programación] Re: [Programació n] Re: [Programación] Cantidad de dat os antes de fgets

Nicolás Aimetti programacion@lugro.org.ar
Fri, 03 Jun 2005 18:12:50 -0300


En el primer mail vos decías que no querías usar threads, pero por lo 
visto ahora te decidiste a usarlos, así que la asumo que vas a usar 
threads...

Por lo que he interpretado vos lanzas una función (o thread) scan_joy() 
para cada dispositivo usb que tenés conectado, y ese thread se encarga 
de leer los datos de dicho dispositivo, por tanto no debería preocuparte 
que un thread en especial esté bloqueado en la espera de datos del 
dispositivo, pues esto en nada afecta a los otros, pues que uno este 
bloqueado en una llamada read() no bloquea a los demás threads.
Otra cosa...
Por ejemplo,
    fgets(buff,IN_BYTES-offset,rfile);
    //permitir a los otros threads hacer algo
    sched_yield();
    sleep(0.5+i/10);
Esté fragmento de código no lo entiendo  muy bien que digamos. O sea, 
primero llamás a fgets, lo cual podría bloquear al thread en cuestión 
hasta que haya datos disponibles. Una vez que esto se cumple, o sea, que 
hay datos disponible, o que hubo algún error (lo cual _debería_ ser 
chequeado), sigue el curso del thread.
[Tené en cuente además que feof no chequea el caso de que haya errores  
en el archivo, como por ejemplo que el archivo se cerro. Por tanto 
deberías hacer algo como:
 if ( fgets(buff,IN_BYTES-offset,rfile) == NULL ) { <tratamiento del 
error> }
al final del mail  pongo un ejemplo de lo que digo acerca de feof, como 
para que te veas lo que te digo, creo que esto tiene mucho que ver en 
por que no anda bien la cosa. ]
Luego comentas "permitir a los otros threads hacer algo" y llamás a 
sched_yield(): por más que no llamases a sched_yield() los demás threads 
deberían poder estar haciendo algo. O sea, no es necesario que llames a 
sched_yield(), es redundante,  por lo menos por lo que yo interpreto de 
lo que acá estoy viendo.
Luego usas  un sleep que según las prioridades de los operadores que 
usas se puede reescribir como:
   sleep( 0.5 + (i/10) );
Por tanto a un entero (i/10) le sumás un double 0.5 lo cual da un double 
(el cual nuevamente es casteado a int), pero la función sleep:
    unsigned int sleep(unsigned int seconds);
toma como parámetro un unsigned int, de lo cual deduzco que en este 
código hay algún tipo de confusión.
Además, suponiendo que necesitases esperar un tiempo como para que 
alguna condición X se cumpliese, entonces te combiene usar la familia de 
funciones pthread_cond_* para conseguir esto.

Se podría emular de alguna manera la función available()  de java, o 
hacer una función para chequear si hay datos disponibles  en el archivo 
antes de leer y demás, pero personalmente pienso que si estás trabajando 
con threads nada de esto es necesario. O sea, cada thread trabaja por su 
cuenta, así que no hay ningún problema con que un thread en particular 
quede bloqueado a la espera de datos, los demás siguen trabajando.

La otra opción que tenés sino es usar en vez de threads la función 
select() o poll(). Pero creo que con threads debería andar todo bien. 

Acerca de lo que pasa cuando desconectas el joypad habría que ver bien 
que pasa en el main() y demás como para poder decir algo.

Ejemplo de por que NO sirve nomás usar feof para controlar si se puede 
leer de un archivo:

#include <stdio.h>
#include <unistd.h>

baja main(void){
    int i=0;
    while(!feof(stdin)){
        char buff[1];
        if (! i++ ){
            if( fclose(stdin)==EOF ){ printf("error!!!"); }
            printf("Se cerro el archivo!!!\n");
            sleep(1);
        }
        printf("y sigue girando... girando...\n");
        if ( fgets(buff,1,stdin) == NULL ) printf("Mienrtras que fgets 
SI da error\n");
    }
    return 0;
}

Espero que te sirva de algo.

Saludos,
             Nicolás.

Gustavo Guillermo Pérez wrote:

>El Jueves, 2 de Junio de 2005 20:44, Nicolás Aimetti escribió:
>  
>
>>Hola...
>>
>>Para husmear en el contenido de un puntero FILE (como es stdin) podes
>>hacer algo así:
>>    #include <stdio.h>
>>    int main(void){
>>        char c = getc(stdin);
>>        printf(">>: %d\n", (stdin->_IO_read_end)-(stdin->_IO_read_ptr));
>>        return 0;
>>    }
>>    
>>
>Bueno, voy a ser más específico, unos amigos me pidieron un programa para 
>arbitrar unos torneos de Taekwondo, usando JoyPads USB que los desarmé y 
>conecté a las cajitas que van a marcar los tantos, (siguen siendo joypads).
>Hice un prototipo en Java pero no quiero usar Java porque lo quiero compilar 
>con la uClibc, entonces traduje el prototipo a "C" porque necesito usar 
>hardware bastante obsoleto para aprovecharlo, bueno, en java tengo una 
>propiedad de un inputstream que es int available() que devuelve cuantos bytes 
>se pueden leer sin bloquear, entonces yo revisaba esa cantidad y sólo si era 
>mayor a 8 bytes que son los que transmite la API del joystick leía un botón, 
>entonces no se bloqueaba la ejecución y podía cerrar el nodo /dev/input/jsX y 
>si alguien desconectaba un joypad, se liberaba ese archivo y el proximo que 
>conectaba se ocupaba por ese, lo cierto es que al pasarlo a "C" no supe como 
>saber si me voy a bloquear leyendo datos o todavía no, porque como es un 
>nodo, no puedo leer el tamaño del archivo porque no tiene tamaño, lo cierto 
>es que usé threads, pthreads para ser más precisos, pero mi programa se clava 
>eternamente al desconectar el joypad, el hilo principal si detecta que se 
>desconectó pero el hilo que leia botones queda trabado en el fgets.
>
>Este es el código de los hilos que leen los botones, la función que es lanzada 
>como hilo por el main();
>
>void scan_joy(int j){
>int i=j;
>FILE *rfile;
>char buff[IN_BYTES];
>char b1[1];
>int offset=0;
>while(1){
>    while(joypads[i].joy_plug==0){sleep(2);}
>
> rfile=fopen(joypads[i].joy_dev,"rb");
> if (rfile!=NULL) {
>//ScanButtons está adentro de esta función
>// fprintf(stderr,"Tratando de leer archivos\n");
>/* while(!feof(rfile)){
> fgets(buff,2,rfile);
> //permitir a los otros threads hacer algo
> sched_yield();
> fprintf(stderr,"[js%i:%i]",i,buff[0]);
> }
>*/
> while(!feof(rfile)){
> b1[0]=buff[2];
> fgets(buff,IN_BYTES-offset,rfile);
> //permitir a los otros threads hacer algo
> sched_yield();
> sleep(0.5+i/10);
> int discard=0;
> printf("Dentro de mientras no sea el fin de archivo js%i:%i:%i:%i:%i:%i:%i:
>%i:%i:%i 
>\n",i,buff[0],buff[1],buff[2],buff[3],buff[4],buff[5],buff[6],buff[7],buff[8]);
> if(b1[0]!=buff[2] && (b1[0]==buff[1] || (b1[0]+1)==buff[1]))
>{offset=1;fprintf(stderr,"MERDEEE[%i]!!!\n",i);printf("MERDEEE[%i]!!!
>\n",i);}else{offset=0;}
> if (buff[6]>=0){
> if(buff[4]==0){if(joypads[i].joy_pressed==1)joypads[i].joy_pressed=0;else 
>discard=1;}
> else{if(joypads[i].joy_pressed==0)joypads[i].joy_pressed=1;else discard=1;}
> joypads[i].joy_button=buff[7]*256*256+buff[6]*256+buff[5];
>   if(!discard){
> if(joypads[i].joy_pressed){
> fprintf(stderr,"JOY:%i:BTN-P:%i\n",i,joypads[i].joy_button);}else{
> fprintf(stderr,"JOY:%i:BTN-R:%i\n",i,joypads[i].joy_button);}
>    }//endif discard
>    else{discard=0;fprintf(stderr,"J__:%i:BTN-R:
>%i\n",i,joypads[i].joy_button);}
> }//endif
> }//end while
>
> fprintf(stderr,"Fin de archivo js%i",i);
> joypads[i].joy_plug=1;
> fclose(rfile);}
> }//end while
> 
>} //end scan_joy(int i)
>
>
>  
>