Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5987
  • 博文数量: 1
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 17
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-12 23:06
文章分类
文章存档

2014年(1)

我的朋友

分类: LINUX

2014-03-12 23:11:48

#include
#include
#include
#include
#include
#include
           
int makethread(void *(*)(void*), void*);

pthread_mutexattr_t attr;
pthread_mutex_t mutex;
           
// fn is timeout_helper , arg is struct to_info
int makethread(void *(*fn)(void*), void *arg)
{
 int err = 0;
 pthread_t tid;
 pthread_attr_t attr;
 void *tret = NULL;
           
 printf("this is makethread\n");
 err = pthread_attr_init(&attr);
 if (err != 0) {
  printf("pthread_attr_init failed\n");
  return err;
 }
 err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);//设置线程分离状态,当线程运行完后,自动回收资源
 if (err == 0) {
  err = pthread_create(&tid, &attr, fn, arg);//在这里arg传到fn当中
  if (err != 0) {
   printf("pthread_create failed\n");
   goto FINISH;
  } else {
   printf("pthread_create success\n");
  }
 } else {
  printf("pthread_attr_setdetachstate failed\n");
 }
FINISH:
  pthread_attr_destroy(&attr);//销毁线程属性
    return err;
}
           
struct to_info {
 void (*to_fn)(void *);  /* function */
 void *to_arg;  /* argument */
 struct timespec to_wait;  /* time to wait */
};
           
#define SECTONSEC 1000000000  /* seconds to nanoseconds */
#define USECTONSEC 1000  /* microseconds to nanoseconds */
           
void err_exit(int err, const char *arg){
 printf("ERROR: %d, DESC: %s\n", err, arg);
 exit(0);
}
   
void* timeout_helper(void *arg)
{
 struct to_info *tip;
           
 tip = (struct to_info*)arg;
 printf("this is timeout_helper\n");
 printf("等待的秒数是:%d, 纳秒是:%d\n", tip->to_wait.tv_sec, tip->to_wait.tv_nsec);
 nanosleep(&tip->to_wait, NULL);//第一个参数是等待唤醒的时间,中间可被信号中断。第二个参数是保留剩余的时候
 (*tip->to_fn)(tip->to_arg);//调用retry函数
 return 0;
}
           
void retry(void *arg)
{
 pthread_mutex_lock(&mutex);
 /* perform retry steps */
 printf("this is retry\n");
 pthread_mutex_unlock(&mutex);
}
           
// func is retry
void timeout(const struct timespec *when, void (*func)(void*), void *arg)
{
 struct timespec now;
 struct timeval tv;
 struct to_info *tip;
 int err;
 printf("this is timeout\n");
 gettimeofday(&tv, NULL);
 now.tv_sec = tv.tv_sec;
 now.tv_nsec = tv.tv_usec * USECTONSEC;//把时间换成纳秒
 if ((when->tv_sec > now.tv_sec) ||
   (when->tv_sec == now.tv_sec && when->tv_nsec > now.tv_nsec)) {//时间未到
  tip = (struct to_info*)malloc(sizeof(struct to_info));
  if (tip != NULL) {
   tip->to_fn = func;/**初始化结构体*/
   tip->to_arg = arg;
   tip->to_wait.tv_sec = when->tv_sec - now.tv_sec;//要等待的秒数
   if (when->tv_nsec >= now.tv_nsec) {
    tip->to_wait.tv_nsec = when->tv_nsec - now.tv_nsec;
   } else {
    tip->to_wait.tv_sec--;
    tip->to_wait.tv_nsec = SECTONSEC - now.tv_nsec + when->tv_nsec;
   }
   err = makethread(timeout_helper, (void*)tip);
   if ( 0 == err) {
    return;
   }
  }
 }
    /**
 * We get here if (a) when <= now, or (b) malloc fails, or
 * (c) we can't make a thread, so we just call the function now.
 */
 (*func)(arg);
}
           
int main(void)
{
 int err, condition, arg;
 struct timeval tv;
 struct timespec when;
           
 condition = 1;
 if ((err = pthread_mutexattr_init(&attr)) != 0) {
  err_exit(err, "pthread_mutexattr_init failed");
 }
 /**/
 if ((err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) != 0) {
 err_exit(err, "can't set recursive type");
 }
 /**/
 if ((err = pthread_mutex_init(&mutex, &attr)) != 0) {
  err_exit(err, "can't create recursive mutex");
 }
 gettimeofday(&tv, NULL);
 when.tv_sec = tv.tv_sec - 1;//设置超时执行,并且设置线程属性为PTHREAD_MUTEX_RECURSIVE用递归加锁方式,否则将会产生死锁
 //when.tv_sec = tv.tv_sec + 1;//默认的线程属性非PTHREAD_MUTEX_RECURSIVE递归加锁方式,线程运行正常
 when.tv_nsec = tv.tv_usec * USECTONSEC;
 pthread_mutex_lock(&mutex);
 if (condition) {
  /* calculate target time "when" */
  timeout(&when, retry, (void*)arg);
 }
 pthread_mutex_unlock(&mutex);
 sleep(2);
 exit(0);
}


/**
1. 注释128~130行(不设置递归互斥量),137行代替136行,超时1秒后,超时线程执行retry函数。由于主进程main和retry是在前后相隔1秒的时间间隔内分别获取互斥量的,因此不会引起互斥量的递归锁定,因此程序能够正确执行;
2. 注释128~130行(不设置递归互斥量),136行代替137行,则95行代码会被执行,main和retry在同一个进程里执行,互斥量嵌套锁定,因此会引起死锁;
3. 解除128~130行的注释(设置递归互斥量),136行代替137行,尽管103行依旧会执行,但是互斥量设置了递归属性,因此程序也能正确执行。
*/


阅读(938) | 评论(1) | 转发(0) |
0

上一篇:没有了

下一篇:没有了

给主人留下些什么吧!~~

啦哆A梦2014-03-13 10:00:25