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/*
* miPrograma.c
* Esta version usa una única hebra servidora, que extrae el primer elemento de la
* lista de peticiones. main inserta nuevas peticiones en la lista, en el orden de menor
* tiempo de aviso La lista está protegida por mutex, y la hebra servidora se suspende al
* menos 1 segundo, en cada iteración, para asegurar que la hebra main tenga oportunidad
* de bloquear el mutex e insertar una nueva petición a la lista.
*/
#include <pthread.h>
#include <time.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct paquete_control {
struct paquete_control *enlace;
int segundos;
time_t tiempo; // segundos desde EPOCH
char mensaje[64];
} paquete_control_t;
pthread_mutex_t lista_mutex = PTHREAD_MUTEX_INITIALIZER; // Creación del cerrojo
paquete_control_t *lista_pet = NULL;
FILE *fp; // para guardar la impresion de los avisos, asi la salida del
// programa no interfiere con la entrada de peticiones.
/*
* funcion que ejecuta la hebra servidora de avisos.
*/
void *servidora (void *lista_pet)
{
paquete_control_t *pcontrol; // Esto es un puntero a un paquete de control
int sleep_time;
int estado;
time_t ahora;
/*
* La hebra cicla siempre, procesando peticiones del usuario.
* La hebra sera "desintegrada" cuando el proceso termine.
*/
while (1) {
estado= pthread_mutex_lock(&lista_mutex); // bloquear el cerrojo lista_mutex
if (estado
!=0) fprintf(stderr
, "Error al bloquear lista_mutex\n"),exit(0);
// asignar el puntero a la direccion de comienzo de "lista_pet"
pcontrol = (paquete_control_t*)lista_pet;
/* Si "lista_pet" esta vacia, asigno a "sleep_time" 1 segundo. La
* suspension durante 1 s. le permitirá a "main" ejecutarse, e intentar
* obtener otra peticion del usuario; si no (la lista de peticiones
* no esta vacia), extraer su primer elemento */
if (pcontrol == NULL){
sleep_time = 1;
}
else{
lista_pet = pcontrol->enlace;
if (pcontrol->tiempo <= ahora) sleep_time = 0;
else sleep_time = pcontrol->tiempo - ahora;
}
/* Ahora, desbloquear "lista_mutex", antes de que la hebra "servidora"
* se suspenda, para que "main" pueda bloquearlo para insertar una nueva
* peticion del usuario,
*/
estado= pthread_mutex_unlock(&lista_mutex);
if (estado
!=0) fprintf(stderr
, "Error al desbloquear lista_mutex\n"),exit(0);
/* Si "sleep_time" > 0, entonces suspender la hebra durante
* ese tiempo; si no, llamar a sched_yield(), y de
* esta forma darle una oportunidad a "main" de ejecutarse,
* si tiene una entrada pendiente del usuario, sin retrasar la
* impresion del aviso si no existiera tal entrada.
*/
if (sleep_time >0) sleep (sleep_time);
else sched_yield();
if (pcontrol != NULL){
fprintf(fp
, "(%d) %s {%ld} \n", pcontrol
->segundos
, pcontrol
->mensaje
, pcontrol->tiempo);
}
}
}
int main (int argc, char *argv[])
{
int estado;
char linea[128];
// declaro punteros para recorrer "lista_pet"
paquete_control_t *pcontrol,*aux,*aux2;
pthread_t hebraServidora;
if ((fp
= fopen("Salidas", "w")) == NULL
) fprintf(stderr
, "Error en la apertura del fichero de salida\n"),exit(0);
if (pthread_create(&hebraServidora,NULL,servidora,(void *)lista_pet))
fprintf(stderr
, "Error al crear la hebra servidora\n"),exit(0);
while (1) {
printf ("Peticion de aviso> "); if (fgets (linea
, sizeof (linea
), stdin
) == NULL
) exit (0); if (strlen (linea
) <= 1) continue;
pcontrol
= (paquete_control_t
*) malloc(sizeof(paquete_control_t
));
if ( sscanf(linea
, "%d %64[^\n]", &pcontrol
->segundos
, pcontrol
->mensaje
) < 2 ){ if (pcontrol->segundos==-1) break;
else{
fprintf(stderr
, "Entrada erronea\n"); }
}
else {
fprintf(fp
, "(%d) %s\n", pcontrol
->segundos
,pcontrol
->mensaje
); estado= pthread_mutex_lock(&lista_mutex);
if (estado
!=0) fprintf(stderr
, "Error al bloquear lista_mutex\n"),exit(0);
pcontrol
->tiempo
=time(NULL
);
/*
* Insertar delante del primer elemento de "lista_pet" que tenga
* un tiempo de aviso >= que el de la nueva peticion que vamos a insertar.
*/
if (lista_pet != NULL){
for (aux=lista_pet ; aux->enlace != NULL ; aux=aux->enlace){
if (pcontrol->tiempo < aux->tiempo){
pcontrol->enlace=aux;
aux2->enlace=pcontrol;
}
aux2=aux;
}
if (aux->enlace == NULL){
aux->enlace = pcontrol;
pcontrol->enlace = NULL;
}
}
else
lista_pet=pcontrol;
estado= pthread_mutex_unlock(&lista_mutex);
if (estado
!=0) fprintf(stderr
, "Error al desbloquear lista_mutex\n"),exit(0); }
}
}
Gracias a todos los forer@s del web.