-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6a6dae2
commit 252cdb6
Showing
7 changed files
with
259 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,3 +30,5 @@ | |
*.exe | ||
*.out | ||
*.app | ||
build | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |