链表+POSIX信号量+条件变量实现的闹铃V2

来源:互联网 发布:百度ocr文字识别 java 编辑:程序博客网 时间:2024/06/05 11:05
这个版本改变了alarm_thread检查链表的方式。
在空链表时采用阻塞等待,在往空链表插入新元素时就会唤醒阻塞等待。
在链表已经有成员时,则alarm_thread等待的采用超时等待策略,直到可以进行闹铃的时候才醒来。当链表中有新的更早的闹铃插入时,则唤醒超时等待的alarm_thread,并将超时等待的世间设置为新的更早的闹铃。
之前的策略是采用轮训的策略来检查链表,并在每次插入新成员的时候都唤醒alarm_thread。

这个实现避免了alarm_thread进行无谓的运行,减少唤醒次数。

#include <stdio.h>#include <stdlib.h>#include <time.h>#include <pthread.h>#include <string.h>#include <unistd.h>typedef struct alarm_list_tag{time_t time;char msg[64];int seconds;struct alarm_list_tag *next;}alarm_list_t;typedef alarm_list_t alarm_list_elem_t;alarm_list_t *alarm_list = NULL;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t cond = PTHREAD_COND_INITIALIZER;alarm_list_elem_t *AllocElem(time_t time, int seconds, char *msg){if(strlen(msg) > 64){fprintf(stderr, "msg too long\n");return NULL;}alarm_list_elem_t *tmp = (alarm_list_elem_t *)malloc(sizeof(alarm_list_elem_t));{//}tmp->time = time;tmp->seconds = seconds;memcpy(tmp->msg, msg, strlen(msg));tmp->next = NULL;return tmp;}int FindDuplicate(alarm_list_t *l, int key){alarm_list_t *p = NULL;int isFound = 0;for( p=l; p!=NULL; p=p->next){if( p->time == key ){isFound = 1;break;}}return isFound;}//in ascending order//no duplicate element//1 on need of sending signalint Insert(alarm_list_t **l, alarm_list_elem_t *elem){//find duplicateif( FindDuplicate(*l, elem->time) ){fprintf(stderr, "already have same timer! time = %ld, seconds = %d\n", elem->time, elem->seconds);return 0;}//empty listif( *l == NULL ){//fprintf(stderr, "alarm_list: empty list\n");*l = elem;return 1;}//new < headerif( (*l)->time > elem->time ){//fprintf(stderr, "alarm_list: new < header\n");elem->next = (*l);*l = elem;return 1;}//header < new and list lenth is 1if((*l)->next == NULL){//fprintf(stderr, "alarm_list: header < new elem && len 1\n");(*l)->next = elem;return 0;}//header < new elem && len > 1{//fprintf(stderr, "alarm_list: header < new elem && len > 1\n");alarm_list_t *prev = (*l);alarm_list_t *p = prev->next;for(; p != NULL; p = p->next){if(prev->time < elem->time && p->time > elem->time){prev->next = elem;elem->next = p;//fprintf(stderr, "case 1\n");return 0;}else if(prev->time < elem->time && p->time < elem->time){prev = p;}else{fprintf(stderr, "duplicate \n");}}//we reach the end of listif( p == NULL ){prev->next = elem;}return 0;}}alarm_list_elem_t *PopList(alarm_list_t **l){if(*l == NULL){//fprintf(stderr, "empty list\n");return NULL;}//fprintf(stderr, "pop elem %d, addr = %p\n", (*l)->seconds, *l);alarm_list_elem_t *tmp = *l;*l = (*l)->next;tmp->next = NULL;return tmp;}void Popfront(alarm_list_t **l){if(*l == NULL){//fprintf(stderr, "empty list\n");return;}alarm_list_elem_t *tmp = *l;(*l) = (*l)->next;free(tmp);}void PrintList(alarm_list_t *l){for(; l != NULL; l=l->next){fprintf(stderr, "Print:time = %ld, seconds = %d, message = %s\n", l->time, l->seconds, l->msg);}}void *alarm_thread(void *arg){int doAlarm = 0;while(1){pthread_mutex_lock(&mutex);if(alarm_list == NULL){pthread_cond_wait(&cond, &mutex);}if(alarm_list != NULL){time_t now = time(NULL);if(now != alarm_list->time){struct timespec to;to.tv_sec = alarm_list->time;to.tv_nsec = 0;//SLEEP_TIME;pthread_cond_timedwait(&cond, &mutex, &to);doAlarm = 1;}if( doAlarm ){now = time(NULL);fprintf(stderr, "alarm!!!now = %ld, time = %ld, seconds = %d, msg = %s\n", now, alarm_list->time, alarm_list->seconds, alarm_list->msg);Popfront(&alarm_list);doAlarm = 0;}}pthread_mutex_unlock(&mutex);}}int main(){pthread_t alarm_pid;pthread_create(&alarm_pid, NULL, &alarm_thread, NULL);int seconds[] = { 15, 16, 25, 23, 7, 14, 28, 39, 100, 20};char msg[64] = "asd";time_t now;int i = 0;while(1){//scanf("%d%s", &seconds, msg);sleep(2);now = time(NULL);alarm_list_elem_t *elem = AllocElem(now+seconds[i], seconds[i], msg);if(elem == NULL){fprintf(stderr, "");}int doSignal = 0;pthread_mutex_lock(&mutex);//fprintf(stderr, "alarm_list before insert addr = %p, seconds = %d\n", alarm_list, seconds[i]);doSignal = Insert(&alarm_list, elem);//fprintf(stderr, "alarm_list after insert addr = %p\n", alarm_list);pthread_mutex_unlock(&mutex);if( doSignal ){pthread_cond_signal(&cond);}i++;if(i == 10){break;}}pthread_join(alarm_pid, NULL);}

0 0
原创粉丝点击