当前位置: 代码迷 >> 综合 >> 从零开始自制实现WebServer(二十)---- C++ High-Performance WebServer源码实现(Timer核心代码部分)
  详细解决方案

从零开始自制实现WebServer(二十)---- C++ High-Performance WebServer源码实现(Timer核心代码部分)

热度:76   发布时间:2023-11-17 16:14:02.0

文章目录

    • 全流程实现博客链接
    • 前引
    • (二十)---- C++ High-Performance WebServer源码实现(Timer核心代码部分)
      • 1、timer.h
      • 1、timer.cc
      • 2、timerqueue.h
      • 2、timerqueue.cc


全流程实现博客链接


从零开始自制实现C++ High-Performance WebServer 全流程记录(基于muduo网络库)


前引


还有两个TimerLogging


(二十)---- C++ High-Performance WebServer源码实现(Timer核心代码部分)


1、timer.h


#ifndef TINY_MUDUO_TIMER_H_
#define TINY_MUDUO_TIMER_H_#include <functional>#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 <utility>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 <unistd.h>
#include <sys/timerfd.h>#include <set>
#include <vector>
#include <memory>
#include <utility>
#include <functional>#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 <assert.h>
#include <sys/timerfd.h>#include <cstring>#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_, '\0', sizeof(new_));memset(&old_, '\0', sizeof(old_));int64_t micro_seconds_dif = timer->expiration().microseconds() - Timestamp::Now().microseconds();if (micro_seconds_dif < 100) {
    micro_seconds_dif = 100;}new_.it_value.tv_sec = static_cast<time_t>(micro_seconds_dif / kMicrosecond2Second);new_.it_value.tv_nsec = static_cast<long>((micro_seconds_dif % kMicrosecond2Second) * 1000);int ret = ::timerfd_settime(timerfd_, 0, &new_, &old_);assert(ret != -1);(void) ret;
}
  相关解决方案