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 // 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); /* 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){ 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 (pthread_create(&hebraServidora,NULL,servidora,(void *)lista_pet)) while (1) { if (pcontrol->segundos==-1) break; else{ } } else { estado= pthread_mutex_lock(&lista_mutex); /* * 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); } } }
Gracias a todos los forer@s del web.