自己写的alarm_cond

 

#include<stdio.h>
#include"errors.h"
#include<pthread.h>
#include<time.h>
typedef struct alarm_tag{
int        seconds;
time_t     alarm_time;
char       message[64];
struct alarm_tag *link;
}alarm_t;
alarm_t *alarm_list=NULL;
pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_t=PTHREAD_COND_INITIALIZER;
time_t current_time=0;
void insert(alarm_t *alarm)
{
    int status;
     alarm_t **last, *next;

     last = &alarm_list;
     next = *last;
     while (next != NULL)
     {
         if (next->alarm_time >= alarm->alarm_time)
         {
             alarm->link = next;
             *last = alarm;
             break;
         }
         last = &next->link;
         next = next->link;
     }
     if (next == NULL) {
         *last = alarm;
         alarm->link = NULL;
     }

/*注意这里链表的插入方法,标准的链表插入中,需要分情况讨论,队头,队中,队尾,这里把队头和队中进行了合并,利用的是一个**last指针,这个指针在刚开始的时候保存的是队头的地址,如果不需要在队头插入,利用last=&next->link,可以保存下一个的节点的地址,找到合适的插入地址,让last指向alarm,alarm指向next即可。本质上和链表的插入方法是一样的,但是巧妙利用了指针。

刚才仔细考虑才知道自己一直存在的误区是链头指针不是元素,它是指向第一个元素的,每个元素都有一个指针指向它,那么只要让这个指向元素的指针链进行传递就可以了,这也就是上面的代码表示的含义。让last指向这个指针链,但是因为这个指针链有两个名字,alarm_list和next->link,所以找一个再找一个指针来指向它们,这就是**last。*/
if(current_time==0||current_time>alarm->alarm_time)
{
   current_time=alarm->alarm_time;
   status=pthread_cond_signal(&cond_t);
   if(status!=0)
    err_abort(status,"Signal cond");
}
}


void *alarm_wait(void *arg)
{
struct timespec cond_time;
alarm_t *alarm;
time_t now;
int status,expiration;

status=pthread_mutex_lock(&mutex);
if(status!=0)
   err_abort(status,"mutex lock");

while(1)
{
   current_time=0;
   while(alarm_list==NULL)
   {
   status=pthread_cond_wait(&cond_t,&mutex);
   if(status!=0)
     err_abort(status,"alarm wait");
   }
   alarm=alarm_list;
   alarm_list=alarm->link;//这一句保证了当前正在使用的闹铃已经不在队列当中
   now=time(NULL);
   cond_time.tv_sec=alarm->alarm_time;
   cond_time.tv_nsec=0;
   current_time=alarm->alarm_time;
   expiration=0;
   if(alarm->alarm_time>now)
   {
    while(current_time==alarm->alarm_time)
    {
     status=pthread_cond_timedwait(&cond_t,&mutex,&cond_time);
     if(status==ETIMEDOUT)
     {
      expiration=1;
      break;
     }
    if(status!=0)
      err_abort(status,"alarm waittime");
    }
   if(!expiration)
    insert(alarm);
   }
   else expiration=1;
   if(expiration)
   {
    printf("%d,%s/n",alarm->seconds,alarm->message);
    free(alarm);//释放空间
   }
}
}
int main(){
pthread_t wait;
alarm_t *new_alarm;
int status;

status = pthread_create(&wait,NULL,alarm_wait,NULL);
if(status!=0)
   err_abort(status,"create alarm thread");
while(1)
{
   printf ("Alarm> ");
   new_alarm=(alarm_t*)malloc(sizeof(alarm_t));
   scanf("%d %s",&new_alarm->seconds,new_alarm->message);//直接scanf也是可以的,当然这里没有原程序的纠错机制,可以另外加上

   new_alarm->alarm_time=time(NULL)+new_alarm->seconds;
   status=pthread_mutex_lock(&mutex);//这里的操作是必须的,保证两个线程对链表的操作是互斥的,以防止插入元素过程中,等待线程启动,造成不可知的后果
   if(status!=0)
     err_abort(status,"mutex lock");
   insert(new_alarm);
   status=pthread_mutex_unlock(&mutex);
   if(status!=0)
     err_abort(status,"mutex unlock");
}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章