linux一个进程实现多个定时器,Linux下的多线程定时器实现

一、功能:

Linux下编写一个程序库,实现定时器的功能,它能为用户提供在同一进程中多次使用的定时器。

二、实现

#include

#include

#include

#include

#include

#include

#include

#include

#define DEFAULT_INTERVAL 1

int TIMER_CNT = 0;

class Timer;                //定时器

class TimerManager;        //定时器管理器

class TimerManager {

friend class Timer;    //友元类,Timer类可分享此类的方法

public:

typedef enum {

TIMER_MANAGER_STOP=0,

TIMER_MANAGER_START

}TimerManagerState;

static TimerManager *instance();    //当前实例

void start();                      //启动当前线程,运行process函数

void stop();                        //终止当前线程

void dump();                        //清理当前剩下的无用定时器

void add_timer(Timer *vtimer);      //线程安全的增加定时器

void remove_timer(Timer *vtimer);  //线程安全的移除定时器

protected:

static void *process(void *);

private:

TimerManager();

void add_timer_unsafe(Timer *vtimer);  //线程非安全的增加定时器,本类使用

void remove_timer_unsafe(Timer *vtimer);//线程非安全的移除定时器,本类使用

static TimerManager *m_instance;

static pthread_mutex_t workmutex;

TimerManagerState m_state;

LIST_HEAD(,Timer) list_;                //链表头

static int mark;

};

class Timer {

friend class TimerManager;

public:

typedef enum {

TIMER_IDLE = 0,

TIMER_ALIVE,

TIMER_TIMEOUT

}TimerState;

Timer(int vinterval,void (*vfunc)(void *),void *vdata);

void start();                          //把自己添加进定时器管理器的链表里

void stop();                            //把自己从定时器管理器的链表里移除

void reset(int vinterval);              //重置

~Timer();

private:

int id;                                //当前定时器的ID

int m_interval;                        //定时器的定时时间,单位为秒

int m_counter;                          //还剩下多少时间,单位为微秒

TimerState m_state;                    //当前定时器的状态

void (*m_func)(void *);

void *m_data;

LIST_ENTRY(Timer) entry_;              //当前定时器在链表中的地址

};

TimerManager *TimerManager::m_instance;

pthread_mutex_t TimerManager::workmutex;

TimerManager::TimerManager() {

pthread_mutex_init(&workmutex,NULL);

}

TimerManager *TimerManager::instance() {

if (m_instance == NULL) {

pthread_mutex_lock(&workmutex);

if (m_instance == NULL)

m_instance = new TimerManager();

pthread_mutex_unlock(&workmutex);

}

return m_instance;

}

void TimerManager::start() {

if (m_state == TIMER_MANAGER_STOP) {

m_state = TIMER_MANAGER_START;

pthread_t pid;

int res = pthread_create(&pid,NULL,process,this);

if (res != 0) {

printf("pthread_create is failed\n");

exit(EXIT_FAILURE);

}

}

}

void TimerManager::stop() {

this->m_state = TIMER_MANAGER_STOP;

}

void TimerManager::dump() {

Timer *item;

pthread_mutex_lock(&workmutex);

LIST_FOREACH(item,&(this->list_),entry_) {

if (item->m_counter == 0) {

printf("Timer%d will be dumped!\n",(int)item->m_data);

item->stop();

}

}

pthread_mutex_unlock(&workmutex);

}

void *TimerManager::process(void *arg) {

pthread_detach(pthread_self());

TimerManager *manage = (TimerManager *)arg;

Timer *item;

struct timeval start,end;

int delay;

struct timeval tm;

gettimeofday(&end,0);

while (manage->m_state == TIMER_MANAGER_START) {

tm.tv_sec = 0;

tm.tv_usec = DEFAULT_INTERVAL * 1000;

start.tv_sec = end.tv_sec;

start.tv_usec = end.tv_usec;

while (select(0,0,0,0,&tm) < 0 && errno == EINTR);

gettimeofday(&end,0);

delay = (end.tv_sec - start.tv_sec) * 1000;

delay += (end.tv_usec - start.tv_usec);

pthread_mutex_lock(&manage->workmutex);

LIST_FOREACH(item, &(manage->list_), entry_) {

//printf("m_data = %d m_counter = %d ",item->m_data,item->m_counter);

if ( item->m_counter < delay)

item->m_counter = 0;

else

item->m_counter -= delay;

//printf("m_data = %d m_counter = %d\n",item->m_data,item->m_counter);

if (item->m_counter == 0) {

if (item->m_func)

item->m_func(item->m_data);

manage->remove_timer_unsafe(item);

item->m_state = Timer::TIMER_TIMEOUT;

}

}

pthread_mutex_unlock(&manage->workmutex);

}

}

void TimerManager::add_timer(Timer* vtimer) {

pthread_mutex_lock(&workmutex);

LIST_INSERT_HEAD(&(this->list_),vtimer,entry_);

pthread_mutex_unlock(&workmutex);

}

void TimerManager::remove_timer(Timer* vtimer) {

pthread_mutex_lock(&workmutex);

LIST_REMOVE(vtimer, entry_);

pthread_mutex_unlock(&workmutex);

}

void TimerManager::add_timer_unsafe(Timer* vtimer) {

LIST_INSERT_HEAD(&(this->list_),vtimer,entry_);

}

void TimerManager::remove_timer_unsafe(Timer* vtimer) {

LIST_REMOVE(vtimer, entry_);

}

还有一个类的代码先不上传,这是我们正在学的Linux一个实验,上传的话万人都交这个代码给老师了。

三、总结:

1、按照之前我写代码的习惯,都是先声明一个类A,,接着依次实现A的方法,然后再声明一个类B,接着依次实现B的方法。

按照这个习惯,如果类A在类B的前面声明,如果类A要调用类B中的方法,就必须在定义之前声明class A,class B,接着把类A声明为类B的友元类,还要把实现放在两个类定义的后面,才不会出错。

按照这个习惯,如果类A要调用类B的方法,类B要调用A的方法,这个要怎么办?到底哪个类放在前面?和上面的情况相似。我们一定要保证某个类在调用另一个类的对象,另一个类的方法都已经实现。否则会出现类似invalid use of incomplete type ‘struct Timer’这样的错误。

2、当类中声明了静态变量,而且未初始化。这时候要在类外单独再声明一次静态变量,这样系统会自动给这些变量分配全局内存空间。这样,后面就可以放心地对静态变量进行赋值了。不然会出现类似于undefined reference to `TimerManager::m_instance'这样的错误。

3、程序中出现了死锁,process中用lock和unlock锁起一段代码,而这段代码中又有用lock和unlock锁起一段断码,这样后一段代码无法执行切程序处于挂起等待状态。

4、我的实现是通过select不断的检查时间,可是select这个函数调用占用了一些时间导致精度误差。如果我尽量少调用select函数,那么实时性不够,如果调用次数很多,那么精确度又不够。在我的代码中折中,选取1s作为调用select的间隔。

5、当Timermanager类调用自身的add_timer_于remove_timer_时可能会发生一些错误,因为没有加锁,但是加锁了就马上死锁,这个问题尚待解决。0b1331709591d260c1c78e86d0c51c18.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值