-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTimer.cpp
77 lines (65 loc) · 2.44 KB
/
Timer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include "Timer.h"
#include "HttpData.h"
#include <sys/time.h>
TimerNode::TimerNode(std::shared_ptr<HttpData> requestData, int timeout)
: deleted_(false), SPHttpData_(requestData) {
struct timeval now;
gettimeofday(&now, NULL);
// 单位是毫秒
expiredTime_ =
(((now.tv_sec % 10000) * 1000) + (now.tv_usec / 1000)) + timeout;
}
TimerNode::~TimerNode() {
if (SPHttpData_) SPHttpData_->handleClose();
}
TimerNode::TimerNode(TimerNode& tn)
: SPHttpData_(tn.SPHttpData_), expiredTime_(0) {}
void TimerNode::update(int timeout){
struct timeval now;
gettimeofday(&now, NULL);
expiredTime_ =
(((now.tv_sec % 10000) * 1000) + (now.tv_usec / 1000)) + timeout;
}
bool TimerNode::isValid() {
struct timeval now;
gettimeofday(&now, NULL);
size_t temp = (((now.tv_sec % 10000) * 1000) + (now.tv_usec / 1000));
if (temp < expiredTime_) {
return true;
}else {
this->setDeleted();
return false;
}
}
void TimerNode::clearReq() {
SPHttpData_.reset();
this->setDeleted();
}
TimerManager::TimerManager() {}
TimerManager::~TimerManager() {}
void TimerManager::addTimer(std::shared_ptr<HttpData> SPHttpData, int timeout) {
SPTimerNode new_node(new TimerNode(SPHttpData, timeout));
timerNodeQueue_.push(new_node);
SPHttpData->linkTimer(new_node);
}
void TimerManager::handleExpiredEvent() {
while(!timerNodeQueue_.empty()) {
SPTimerNode ptimer_now = timerNodeQueue_.top();
if (ptimer_now->isDeleted() || !ptimer_now->isValid())
timerNodeQueue_.pop();
else
break;
}
}
/* 处理逻辑是这样的~
因为(1) 优先队列不支持随机访问
(2) 即使支持,随机删除某节点后破坏了堆的结构,需要重新更新堆结构。
所以对于被置为deleted的时间节点,会延迟到它(1)超时 或
(2)它前面的节点都被删除时,它才会被删除。
一个点被置为deleted,它最迟会在TIMER_TIME_OUT时间后被删除。
这样做有两个好处:
(1) 第一个好处是不需要遍历优先队列,省时。
(2)
第二个好处是给超时时间一个容忍的时间,就是设定的超时时间是删除的下限(并不是一到超时时间就立即删除),如果监听的请求在超时后的下一次请求中又一次出现了,
就不用再重新申请RequestData节点了,这样可以继续重复利用前面的RequestData,减少了一次delete和一次new的时间。
*/