- 全流程实现博客链接
- 前引
- (二十)---- C++ High-Performance WebServer源码实现(Timer核心代码部分)
- 1、timer.h
- 1、timer.cc
- 2、timerqueue.h
- 2、timerqueue.cc
全流程实现博客链接
从零开始自制实现C++ High-Performance WebServer 全流程记录(基于muduo网络库)
前引
还有两个Timer
和Logging
(二十)---- C++ High-Performance WebServer源码实现(Timer核心代码部分)
1、timer.h
#ifndef TINY_MUDUO_TIMER_H_
#define TINY_MUDUO_TIMER_H_
#include
#include "timestamp.h"
#include "noncopyable.h"
namespace tiny_muduo {
class Timer : public NonCopyAble {
public:
typedef std::function<void()> BasicFunc;
Timer(Timestamp timestamp, BasicFunc&& cb, double interval);
void Restart(Timestamp now) {
expiration_ = Timestamp::AddTime(now, interval_);
}
void Run() const {
callback_();
}
Timestamp expiration() const { return expiration_; }
bool repeat() const { return repeat_; }
private:
Timestamp expiration_;
BasicFunc callback_;
double interval_;
bool repeat_;
};
} // namespace tiny_muduo
#endif
1、timer.cc
#include "timer.h"
#include
using namespace tiny_muduo;
Timer::Timer(Timestamp expiration, BasicFunc&& cb, double interval = 0.0)
: expiration_(expiration),
callback_(std::move(cb)),
interval_(interval),
repeat_(interval > 0.0) {
}
2、timerqueue.h
#ifndef TINY_MUDUO_TIMERQUEUE_H_
#define TINY_MUDUO_TIMERQUEUE_H_
#include
#include
#include
#include
#include
#include
#include
#include "timer.h"
#include "timestamp.h"
#include "noncopyable.h"
#include "logging.h"
namespace tiny_muduo {
class EventLoop;
class Channel;
class TimerQueue : public NonCopyAble {
public:
typedef std::function<void()> BasicFunc;
TimerQueue(EventLoop* loop);
~TimerQueue();
void ReadTimerFd() {
uint64_t read_byte;
ssize_t readn = ::read(timerfd_, &read_byte, sizeof(read_byte));
if (readn != sizeof(read_byte)) {
LOG_ERROR << "TimerQueue::ReadTimerFd read_size < 0";
}
}
void HandleRead() {
ReadTimerFd();
Timestamp expiration_time(Timestamp::Now());
active_timers_.clear();
auto end = timers_.lower_bound(TimerPair(Timestamp::Now(), reinterpret_cast<Timer*>(UINTPTR_MAX)));
active_timers_.insert(active_timers_.end() , timers_.begin(), end);
timers_.erase(timers_.begin(), end);
for (const auto& timerpair : active_timers_) {
timerpair.second->Run();
}
ResetTimers();
}
void ResetTimers() {
for (auto& timerpair: active_timers_) {
if ((timerpair.second)->repeat()) {
auto timer = timerpair.second;
timer->Restart(Timestamp::Now());
Insert(timer);
} else {
delete timerpair.second;
}
}
if (!timers_.empty()) {
ResetTimer(timers_.begin()->second);
}
}
bool Insert(Timer* timer) {
bool reset_instantly = false;
if (timers_.empty() || timer->expiration() < timers_.begin()->first ) {
reset_instantly = true;
}
timers_.emplace(std::move(TimerPair(timer->expiration(), timer)));
return reset_instantly;
}
void AddTimerInLoop(Timer* timer) {
bool reset_instantly = Insert(timer);
if (reset_instantly) {
ResetTimer(timer);
}
}
void ResetTimer(Timer* timer);
void AddTimer(Timestamp timestamp, BasicFunc&& cb, double interval);
private:
typedef std::pair<Timestamp, Timer*> TimerPair;
typedef std::set<TimerPair> TimersSet;
typedef std::vector<TimerPair> ActiveTimers;
EventLoop* loop_;
int timerfd_;
std::unique_ptr<Channel> channel_;
TimersSet timers_;
ActiveTimers active_timers_;
};
} // namesapce tiny_muduo
#endif
2、timerqueue.cc
#include "timerqueue.h"
#include
#include
#include
#include "channel.h"
using namespace tiny_muduo;
TimerQueue::TimerQueue(EventLoop* loop)
: loop_(loop),
timerfd_(::timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC)),
channel_(new Channel(loop_, timerfd_)) {
channel_->SetReadCallback(std::bind(&TimerQueue::HandleRead, this));
channel_->EnableReading();
}
TimerQueue::~TimerQueue() {
channel_->DisableAll();
loop_->Remove(channel_.get());
close(timerfd_);
for (const auto& timerpair : timers_) {
delete timerpair.second;
}
}
void TimerQueue::AddTimer(Timestamp timestamp, BasicFunc&& cb, double interval) {
Timer* timer(new Timer(timestamp, std::move(cb), interval));
loop_->RunOneFunc(std::bind(&TimerQueue::AddTimerInLoop, this, timer));
}
void TimerQueue::ResetTimer(Timer* timer) {
struct itimerspec new_;
struct itimerspec old_;
memset(&new_, ','sizeof ()new_);memset
(&,old_',' sizeof( ))old_;int64_t=
expiration micro_seconds_dif ( timer->).microseconds()-Timestamp :: Now().microseconds();if(
< 100micro_seconds_dif ) =100 {
micro_seconds_dif ; }.
.
new_=it_valuestatic_casttv_sec < (/time_t>)
micro_seconds_dif ; kMicrosecond2Second..
new_=it_valuestatic_casttv_nsec < long((>%
)micro_seconds_dif * kMicrosecond2Second1000 ) ;int=
:: ret timerfd_settime (,0timerfd_, &, &new_) ;old_assert(
!=-ret 1 );(void
);} ret
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)