Foros del Web » Programación para mayores de 30 ;) » C/C++ »

No sé que hacer ya con este código...

Estas en el tema de No sé que hacer ya con este código... en el foro de C/C++ en Foros del Web. Hola foreros del web , estoy programando en 'c' y tengo un problema porque lo que quiero que me haga este código no me lo ...
  #1 (permalink)  
Antiguo 07/10/2011, 04:21
 
Fecha de Ingreso: diciembre-2010
Mensajes: 52
Antigüedad: 13 años, 4 meses
Puntos: 5
Desacuerdo No sé que hacer ya con este código...

Hola foreros del web, estoy programando en 'c' y tengo un problema porque lo que quiero que me haga este código no me lo hace, he usado el ddd y no veo el problema, es un poco engorroso ver que hace mi código pero se lo agradecería mucho al que fuera capaz.

Se trata de un programa concurrente en el que uso un cerrojo donde una hebra saca recursos de una estructura enlazada y el main mete recursos en la misma estructura, para que no lo hagan a la vez uso el cerrojo.

Código C:
Ver original
  1. /*
  2.  * miPrograma.c
  3.  * Esta version usa una única hebra servidora, que extrae el primer elemento de la
  4.  * lista de peticiones. main inserta nuevas peticiones en la lista, en el orden de menor
  5.  * tiempo de aviso La lista está protegida por mutex, y la hebra servidora se suspende al  
  6.  * menos  1 segundo, en cada iteración, para asegurar que la hebra main tenga oportunidad
  7.  * de bloquear el mutex e insertar una nueva petición a la lista.
  8.  */
  9.  
  10. #include <pthread.h>
  11. #include <time.h>
  12. #include <errno.h>
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16.  
  17. typedef struct paquete_control {
  18.   struct paquete_control       *enlace;
  19.   int                          segundos;
  20.   time_t                       tiempo;                              // segundos desde EPOCH
  21.   char                         mensaje[64];
  22. } paquete_control_t;
  23.  
  24. pthread_mutex_t lista_mutex = PTHREAD_MUTEX_INITIALIZER;        // Creación del cerrojo
  25. paquete_control_t *lista_pet = NULL;
  26.  
  27. FILE  *fp;  // para guardar la impresion de los avisos, asi la salida del
  28.                   // programa no interfiere con la entrada de peticiones.
  29.  
  30. /*
  31.  * funcion que ejecuta la hebra servidora de avisos.
  32.  */
  33. void *servidora (void *lista_pet)
  34. {
  35.     paquete_control_t *pcontrol;        // Esto es un puntero a un paquete de control
  36.    
  37.    
  38. int sleep_time;
  39. int estado;
  40.     time_t ahora;    
  41.  
  42.   /*
  43.    * La hebra cicla siempre, procesando peticiones del usuario.
  44.    * La hebra sera "desintegrada" cuando el proceso termine.
  45.    */
  46.     while (1) {
  47.    
  48.         estado= pthread_mutex_lock(&lista_mutex);       // bloquear el cerrojo lista_mutex
  49.      
  50.                 if (estado !=0) fprintf(stderr, "Error al bloquear lista_mutex\n"),exit(0);
  51.  
  52.      // asignar el puntero a la direccion de comienzo de "lista_pet"
  53.         pcontrol = (paquete_control_t*)lista_pet;
  54.  
  55.      
  56.     /* Si "lista_pet" esta vacia, asigno a "sleep_time" 1 segundo. La
  57.      * suspension durante 1 s. le permitirá a "main" ejecutarse, e intentar
  58.      * obtener otra peticion del usuario; si no (la lista de peticiones
  59.      * no esta vacia), extraer su primer elemento */
  60.         if (pcontrol == NULL){
  61.             sleep_time = 1;
  62.         }
  63.  
  64.         else{
  65.             lista_pet = pcontrol->enlace;
  66.             ahora = time(NULL);
  67.             if (pcontrol->tiempo <= ahora) sleep_time = 0;
  68.        
  69.             else sleep_time = pcontrol->tiempo - ahora;
  70.         }
  71.  
  72.  
  73.     /* Ahora, desbloquear "lista_mutex", antes de que la hebra "servidora"
  74.      * se suspenda, para que "main" pueda bloquearlo para insertar una nueva
  75.      * peticion del usuario,
  76.      */
  77.         estado= pthread_mutex_unlock(&lista_mutex);
  78.         if (estado !=0) fprintf(stderr, "Error al desbloquear lista_mutex\n"),exit(0);
  79.  
  80.      
  81.  
  82.     /* Si "sleep_time" > 0, entonces suspender la hebra durante
  83.      * ese tiempo; si no, llamar a sched_yield(), y de
  84.      * esta forma darle una oportunidad a "main" de ejecutarse,
  85.      * si tiene una entrada pendiente del usuario, sin retrasar la
  86.      * impresion del aviso si no existiera tal entrada.
  87.      */
  88.         if (sleep_time >0) sleep (sleep_time);
  89.    
  90.         else sched_yield();
  91.      
  92.         if (pcontrol != NULL){
  93.             fprintf(fp, "(%d) %s {%ld} \n", pcontrol->segundos, pcontrol->mensaje,
  94. pcontrol->tiempo);
  95.             free(pcontrol);
  96.         }
  97.      
  98.     }
  99. }
  100.  
  101.  
  102.  
  103. int main (int argc, char *argv[])
  104. {
  105.     int estado;  
  106.     char linea[128];
  107.  
  108.      // declaro punteros para recorrer "lista_pet"
  109.     paquete_control_t  *pcontrol,*aux,*aux2;
  110.  
  111.  
  112.     pthread_t hebraServidora;
  113.  
  114.  
  115.     if ((fp = fopen("Salidas", "w")) == NULL)
  116.         fprintf(stderr, "Error en la apertura del fichero de salida\n"),exit(0);
  117.      
  118.     if (pthread_create(&hebraServidora,NULL,servidora,(void *)lista_pet))
  119.         fprintf(stderr, "Error al crear la hebra servidora\n"),exit(0);
  120.        
  121.     while (1) {
  122.         printf ("Peticion de aviso> ");
  123.         if (fgets (linea, sizeof (linea), stdin) == NULL) exit (0);
  124.         if (strlen (linea) <= 1) continue;
  125.  
  126.     pcontrol= (paquete_control_t*) malloc(sizeof(paquete_control_t));
  127.  
  128.         if ( sscanf(linea, "%d %64[^\n]", &pcontrol->segundos, pcontrol->mensaje) < 2 ){
  129.             if (pcontrol->segundos==-1) break; 
  130.            
  131.             else{
  132.                 fprintf(stderr, "Entrada erronea\n");
  133.                 free(pcontrol);
  134.             }
  135.         }
  136.         else {
  137.                 fprintf(fp, "(%d) %s\n", pcontrol->segundos,pcontrol->mensaje);
  138.             estado= pthread_mutex_lock(&lista_mutex);
  139.  
  140.             if (estado !=0) fprintf(stderr, "Error al bloquear lista_mutex\n"),exit(0);
  141.  
  142.             pcontrol->tiempo=time(NULL);
  143.      
  144.          /*
  145.          * Insertar delante del primer  elemento de  "lista_pet" que tenga
  146.          * un tiempo de aviso >= que el de la nueva peticion que vamos a insertar.
  147.          */
  148.  
  149.             if (lista_pet != NULL){
  150.                 for (aux=lista_pet ; aux->enlace != NULL ; aux=aux->enlace){
  151.                     if (pcontrol->tiempo < aux->tiempo){
  152.                         pcontrol->enlace=aux;
  153.                         aux2->enlace=pcontrol;
  154.                     }
  155.                     aux2=aux;
  156.                         }
  157.                 if (aux->enlace == NULL){
  158.                     aux->enlace = pcontrol;
  159.                     pcontrol->enlace = NULL;
  160.                 }
  161.             }
  162.             else
  163.                 lista_pet=pcontrol;
  164.  
  165.             estado= pthread_mutex_unlock(&lista_mutex);
  166.             if (estado !=0) fprintf(stderr, "Error al desbloquear lista_mutex\n"),exit(0);
  167.         }
  168.  
  169.     }
  170.  
  171.     if (fclose(fp)) fprintf(stderr, "Error al cerrar el fichero\n");
  172. }

Gracias a todos los forer@s del web.
  #2 (permalink)  
Antiguo 11/10/2011, 10:43
 
Fecha de Ingreso: diciembre-2010
Mensajes: 52
Antigüedad: 13 años, 4 meses
Puntos: 5
Pregunta Respuesta: No sé que hacer ya con este código...

Hago reflotar esta hebra para ver si algún alma generosa me puede ayudar, 4 días después no sé porque no me funciona esta ****** de código...
  #3 (permalink)  
Antiguo 15/10/2011, 12:25
 
Fecha de Ingreso: diciembre-2010
Mensajes: 52
Antigüedad: 13 años, 4 meses
Puntos: 5
Exclamación Respuesta: No sé que hacer ya con este código...

¿Qué ocurre que veis el código demasiado largo?
¿No entienden C?
¿No saben programar con threads?
Necesito ayuda gente, por favor.
  #4 (permalink)  
Antiguo 16/10/2011, 04:30
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 15 años, 10 meses
Puntos: 61
Respuesta: No sé que hacer ya con este código...

Sugiero agregar ejecuciones de tu programa, las salidas esperadas y como te das cuenta que no está funcionando. Como se trata de concurrencia, varias ejecuciones, varias salidas.

Dejar un programa que "no funciona" y hacer adivinar que es lo que ves que está mal o como te das cuenta de ello te hará obtener lo que has obtenido: Ninguna respuesta y 1 sugerencia. Dicho de otra forma, ayudanos a ayudarte.
  #5 (permalink)  
Antiguo 16/10/2011, 09:49
 
Fecha de Ingreso: diciembre-2010
Mensajes: 52
Antigüedad: 13 años, 4 meses
Puntos: 5
Información Respuesta: No sé que hacer ya con este código...

Pues yo lo que intentaba era hacer como una agenda, ejecuto mi programa y debería salir esto:

Código:
Insertar aviso> (cursor aqui)
Entonces yo escribo un numero que indica el tiempo y un mensaje a dejar, entonces pasado esos segundos me escribirá en un fichero el mensaje que puse. Se pueden insertar tantos avisos como se quiera y el programa finalizará cuando el programa dé un error o se pulse el 'ctrl-c'

Y lo único que me hace es crear el fichero pero no sale nada en el fichero. Gracias por responder Calgary.
  #6 (permalink)  
Antiguo 16/10/2011, 20:45
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 15 años, 10 meses
Puntos: 61
Respuesta: No sé que hacer ya con este código...

Parece estar bien, compile tu programa, lo ejecute y esto me dio a mi: (termine la ejecucion con -1, no con Control-C)


ubuntu:/tmp/dev$ ./t
Peticion de aviso> 3 hola
Peticion de aviso> 1 mensaje
Peticion de aviso> 0 0
Peticion de aviso> -1
ubuntu:/tmp/dev$ cat Salidas
(3) hola
(1) mensaje
(0) 0
  #7 (permalink)  
Antiguo 17/10/2011, 04:34
 
Fecha de Ingreso: diciembre-2010
Mensajes: 52
Antigüedad: 13 años, 4 meses
Puntos: 5
Respuesta: No sé que hacer ya con este código...

Entiendo, el ctrl-c no deja imprimir en el fichero, pero aún así, ¿te salio hola tres segundos despues de que presionaras enter? ¿te salio mensaje un segundo despues? si pusiste 0 0 antes de un segundo después de presionar enter con 1 mensaje en el fichero se te tenía que colocar antes...
Gracias por tu ayuda.
  #8 (permalink)  
Antiguo 17/10/2011, 10:13
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 15 años, 10 meses
Puntos: 61
Respuesta: No sé que hacer ya con este código...

No escribe inmediatamente en el archivo, ni escribe los segundos indicados despues, sino que lo hace al final.
Esto es debido a que al thread le estas pasando la una direccion de memoria que no se modifica mas
  #9 (permalink)  
Antiguo 17/10/2011, 10:15
 
Fecha de Ingreso: junio-2008
Ubicación: Seattle, USA
Mensajes: 733
Antigüedad: 15 años, 10 meses
Puntos: 61
Respuesta: No sé que hacer ya con este código...

Sugiero que crees una estructura que sea la cabeza de la lista, que contenga la direccion de memoria del primer nodo.
Es la direccion de esta cabeza de lista la que pasas a la funcion servidora y es a esa la que lees y actualizas.
Haciendo esto, tu programa escribira correctamente al archivo, respetando el sleep que estableciste. No escribas en el main hacia el archivo.

e.g.


struct lista {
paquete_control_t * first;
} lista_pet;


en main

lista_pet.first = NULL;

inicias el thread pasando la direccion de memoria de lista_pet
y luego desreferencias a este puntero, llegando o actualizado el puntero a "first".

Última edición por CalgaryCorpus; 17/10/2011 a las 10:26

Etiquetas: funcion, programa, struct
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta

SíEste tema le ha gustado a 2 personas




La zona horaria es GMT -6. Ahora son las 05:26.