Skip to content

Commit

Permalink
add the timer manager
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidAlphaFox committed Nov 28, 2024
1 parent 6a6dae2 commit 252cdb6
Show file tree
Hide file tree
Showing 7 changed files with 259 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,5 @@
*.exe
*.out
*.app
build
.idea
15 changes: 15 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.25)
project(czsocket VERSION 1.0.1 DESCRIPTION "socket library for chez scheme")
set(CMAKE_CXX_STANDARD 17)

add_library(${PROJECT_NAME} SHARED
src/timer_manager.cpp
src/timer_handler.cpp
)

add_executable(test
src/main.cpp
)
target_link_libraries(test
${PROJECT_NAME}
)
58 changes: 58 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include <memory>
#include <iostream>
#include <chrono>
#include <thread>
#include "timer_handler.h"
#include "timer_manager.h"

class my_timer_handler :public timer_handler {
public:
my_timer_handler() = default;
~my_timer_handler(){
std::cout << "the my_timer_handler destruct" << std::endl;
}
void handle_timeout() override {
std::cout << "the my_timer_handler handle timeout" << std::endl;
}
};


void log_timer_item(const timer_item& item)
{
std::shared_ptr<timer_handler> _handler = item.handler.lock();
if(_handler != nullptr) {
if(item.remain_millisecond <= 0) {
_handler->handle_timeout();
}
std::cout << "handler is:" << _handler << " handler reference count: "<< _handler.use_count() << " next_expired_time: " << item.next_expired_time
<< " remain_millisecond: " << item.remain_millisecond << std::endl;
}

}



int main() {
std::shared_ptr <timer_manager> _timer_manager = std::make_shared<timer_manager>();
std::shared_ptr <timer_handler> _handler1 = std::make_shared<my_timer_handler>();
std::shared_ptr <timer_handler> _handler2 = std::make_shared<my_timer_handler>();
std::cout << "handler1: " << _handler1 << " handler2: " << _handler2 << std::endl;
_timer_manager->add_item(_handler1, 500, true);
_timer_manager->add_item(_handler2, 400, false);
timer_item _item;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
for(int i = 0; i < 7; i ++){
std::cout << "round: " << i << std::endl;
_timer_manager->get_latest_item(_item);
log_timer_item(_item);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
_timer_manager->remove_first();
_item.handler.reset();
if( i == 5){
_timer_manager->remove_item(_handler1);
}
}

std::cout << "end of life" << std::endl;
return 0;
}
11 changes: 11 additions & 0 deletions src/timer_handler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//
// Created by david on 11/28/24.
//

#include "timer_handler.h"
timer_handler::~timer_handler() {
}

void timer_handler::handle_timeout() {
std::cout << "the timer_handler handle timeout" << std::endl;
}
19 changes: 19 additions & 0 deletions src/timer_handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// Created by david on 11/28/24.
//

#ifndef CHEZ_SOCKET_TIMER_HANDLER_H
#define CHEZ_SOCKET_TIMER_HANDLER_H
#include <string>
#include <iostream>


class timer_handler {
public:
timer_handler() = default;
virtual ~timer_handler();
virtual void handle_timeout();
};


#endif //CHEZ_SOCKET_TIMER_HANDLER_H
112 changes: 112 additions & 0 deletions src/timer_manager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@

#include <sstream>
#include <typeinfo>
#include <cassert>
#include <chrono>
#include <limits>
#include <memory>
#include "timer_manager.h"

//最大时长为1天
const unsigned MAX_TIMER_MILLISECOND = 86400000;


uint64_t current_millisecond() {
std::chrono::milliseconds current = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch());
return current.count();
}

bool operator<(const timer_item &left, const timer_item &right) {
//比较两个时间对象大小,左侧减右侧是负数的,那就代表是小
return ((int64_t)(left.next_expired_time - right.next_expired_time) < 0);
}

timer_manager::timer_manager() {

}

timer_manager::~timer_manager() {

}

bool timer_manager::add_item(std::weak_ptr <timer_handler> handler, uint64_t millisecond, bool is_cycled) {
//查看是否是已经存在的handler,如果存在同样的handler就直接返回
if (is_repeat_item(handler)) {
return false;
}
//强限定,时间不能超高一天
assert(millisecond < MAX_TIMER_MILLISECOND);
//获取当前时间的时间戳,转化成毫秒

uint64_t next_expired_time = current_millisecond() + millisecond;
timer_item item;
item.handler = handler;
item.is_cycled = is_cycled;
item.next_expired_time = next_expired_time;
item.period = millisecond;
item.remain_millisecond = UINT64_MAX;
timer_set::iterator timer = _expired_set.insert(item);
_handlers.insert(std::pair < std::weak_ptr < timer_handler > , timer_set::iterator > (handler, timer));
assert(_expired_set.size() == _handlers.size());
return true;
}

bool timer_manager::is_repeat_item(std::weak_ptr <timer_handler> handler) {
timer_map::iterator it = _handlers.find(handler);
if (it != _handlers.end()) {
return true;
}
return false;
}

void timer_manager::remove_item(std::weak_ptr <timer_handler> handler) {
timer_map::iterator it = _handlers.find(handler);
if (it != _handlers.end()) {
//从超时集合中删除,对应的对象,然后在从map中删除
_expired_set.erase(it->second);
_handlers.erase(it);
}
assert(_expired_set.size() == _handlers.size());
}

bool timer_manager::has_timer_item() {
return (_expired_set.size() != 0);
}

void timer_manager::get_latest_item(timer_item &result) {
timer_set::iterator begin = _expired_set.begin();
result = *begin;
uint64_t current = current_millisecond();
if (less_than(result.next_expired_time, current)) {
result.remain_millisecond = 0;
} else {
result.remain_millisecond = offset(result.next_expired_time, current);
}
}

void timer_manager::remove_first() {
if(_expired_set.size() > 0) {
timer_set::iterator iter = _expired_set.begin();
timer_item temp = *iter;
_expired_set.erase(iter);
timer_map::iterator it;
it = _handlers.find(temp.handler);
if (it != _handlers.end()) {
_handlers.erase(it);
}
// 如果是循环定时,直接再次加回来
if (temp.is_cycled) {
add_item(temp.handler, temp.period, true);
}
assert(_expired_set.size() == _handlers.size());
}
}

bool timer_manager::less_than(uint64_t left, uint64_t right) {
return (((int64_t)(left - right)) < 0);
}

uint64_t timer_manager::offset(uint64_t left, uint64_t right) {
return left - right;
}
42 changes: 42 additions & 0 deletions src/timer_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#ifndef CHEZ_SOCKET_TIMER_MANAGER_H
#define CHEZ_SOCKET_TIMER_MANAGER_H

#include <map>
#include <set>
#include <memory>

class timer_handler;

struct timer_item
{
std::weak_ptr<timer_handler> handler;
uint64_t remain_millisecond;

bool is_cycled;
uint64_t period;
uint64_t next_expired_time;
};

class timer_manager
{
public:
timer_manager();
virtual ~timer_manager();
bool add_item(std::weak_ptr<timer_handler> handler, uint64_t millisecond,bool is_cycled = false);
void remove_item( std::weak_ptr<timer_handler> handler);
bool has_timer_item();
void get_latest_item( timer_item& result );
void remove_first();
protected:
bool less_than( uint64_t left, uint64_t right );
uint64_t offset( uint64_t left, uint64_t right );
bool is_repeat_item(std::weak_ptr<timer_handler> handler);
private:
//使用一个排序的set,把最先超时的handler放在最前面
typedef std::multiset<timer_item> timer_set;
timer_set _expired_set;
typedef std::map<std::weak_ptr<timer_handler>, timer_set::iterator,std::owner_less<>> timer_map;
timer_map _handlers;
};

#endif //CHEZ_SOCKET_TIMER_MANAGER_H

0 comments on commit 252cdb6

Please sign in to comment.