CodeFree/6_solution/高性能定时器/最小堆定时器/heap_timer.hpp

274 lines
7.1 KiB
C++
Raw Normal View History

2024-12-26 13:57:27 +08:00
#ifndef _LIB_SRC_HEAD_TIMER_H_
#define _LIB_SRC_HEAD_TIMER_H_
#include "timer_common.hpp"
#include <iostream>
#define HEAD_DEFAULT_SIZE 128
// 定时器数据结构的定义
template <typename _User_Data>
class HeapTimer {
public:
HeapTimer() = default;
HeapTimer(int msec) {
timer.setTimeout(msec);
}
~HeapTimer() {}
void setTimeout(time_t timeout) {
timer.setTimeout(timeout);
}
time_t getExpire() {
return timer.getExpire();
}
void setUserData(_User_Data* userData) {
timer.setUserData(userData);
}
int getPos() {
return _pos;
}
void setPos(int pos) {
this->_pos = pos;
}
void handleTimeout() {
timer.handleTimeout();
}
using TimeOutCbFunc = void (*)(_User_Data*);
void setCallBack(TimeOutCbFunc callBack) {
timer.setCallBack(callBack);
}
public:
Timer<_User_Data> timer;
private:
// 保存该定时器在数组中的位置,便于查找删除
int _pos;
};
/*
1Timer包装呢HeapTimer内部嵌合了Timer与pos
Timer数据结构
*/
// 定时容器,使用最小堆实现
template <typename _UData>
class HeapTimerContainer : public ITimerContainer<_UData> {
public:
HeapTimerContainer();
HeapTimerContainer(int capacity);
HeapTimerContainer(HeapTimer<_UData>** initArray, int arrSize, int capacity);
virtual ~HeapTimerContainer() override;
public:
virtual void tick() override;
Timer<_UData>* addTimer(time_t timeout) override;
void delTimer(Timer<_UData>* timer) override;
void resetTimer(Timer<_UData>* timer, time_t timeout) override;
int getMinExpire() override;
Timer<_UData>* top();
void popTimer();
private:
void percolateDown(int hole);
void percolateUp(int hole);
void resize();
bool isEmpty();
private:
HeapTimer<_UData>** _array; // 堆数据
int _capacity; // 堆数组的容量
int _size; // 当前包含的元素
};
template <typename _UData>
HeapTimerContainer<_UData>::HeapTimerContainer() : HeapTimerContainer(HEAD_DEFAULT_SIZE) {}
// 初始化一个大小为cap的空堆
template <typename _UData>
HeapTimerContainer<_UData>::HeapTimerContainer(int capacity) {
this->_capacity = capacity;
this->_size = 0;
// 不理解为什么加个nullptr
_array = new HeapTimer<_UData>* [capacity]{nullptr};
}
// 用已有数组来初始化堆
template <typename _UData>
HeapTimerContainer<_UData>::HeapTimerContainer(HeapTimer<_UData>** initArray,
int arrSize, int capacity) : _size(arrSize) {
if(capacity < arrSize) {
this->_capacity = capacity = 2 * arrSize;
}
_array = new HeapTimer<_UData>*[capacity];
for (int i = 0; i < capacity; i++) {
_array[i] = nullptr;
}
if (arrSize > 0) {
for (int i = 0; i < arrSize; i++) {
_array[i] = initArray[i];
}
for (int i = (_size - 1) / 2; i >= 0; i--) {
percolateDown(i);
}
}
}
template<typename _UData>
HeapTimerContainer<_UData>::~HeapTimerContainer() {
if(_array) {
for(int i = 0; i < _size; i++) {
delete _array[i];
}
delete []_array;
}
}
template <typename _UData>
void HeapTimerContainer<_UData>::tick() {
std::cout << "-----------------tick-----------------" << std::endl;
HeapTimer<_UData>* tmp = _array[0];
time_t cur = getMsec();
// 循环处理到期的定时器
while(!isEmpty()) {
if(!tmp) break;
if(tmp->getExpire() > cur) break;
tmp->handleTimeout();
// 将堆顶元素删除,同时生成新的堆顶定时器
popTimer();
tmp = _array[0];
}
}
// 获取一个定时器
template <typename _UData>
Timer<_UData>* HeapTimerContainer<_UData>::addTimer(time_t timeout) {
if(_size >= _capacity) this->resize();
int hole = _size++;
HeapTimer<_UData>* timer = new HeapTimer<_UData>(timeout);
_array[hole] = timer;
percolateUp(hole);
return &timer->timer;
}
// 删除目标定时器
template <typename _UData>
void HeapTimerContainer<_UData>::delTimer(Timer<_UData>* timer) {
if(!timer) return;
timer->setCallBack(nullptr);
timer->setUserData(nullptr);
}
// 重置一个定时器
template <typename _UData>
void HeapTimerContainer<_UData>::resetTimer(Timer<_UData>* timer, time_t timeout) {
HeapTimer<_UData>* htimer = reinterpret_cast<HeapTimer<_UData>*>(timer);
int pos = htimer->getPos();
int lastPos = _size - 1;
if(pos != lastPos) {
HeapTimer<_UData>* temp = _array[pos];
_array[pos] = _array[lastPos];
_array[lastPos] = temp;
}
timer->setTimeout(timeout);
percolateDown(pos);
percolateUp(lastPos);
}
// 获取容器中超时值最小的值
template <typename _UData>
int HeapTimerContainer<_UData>::getMinExpire() {
Timer<_UData>* timer = top();
if(timer) return timer->getExpire();
return -1;
}
// 获取顶部的定时器
template <typename _UData>
Timer<_UData>* HeapTimerContainer<_UData>::top(){
if(!isEmpty()) return nullptr;
return &_array[0]->timer;
}
template <typename _UData>
void HeapTimerContainer<_UData>::popTimer() {
if(!isEmpty()) return;
if(_array[0]) {
delete _array[0];
_array[0] = _array[--_size];
percolateDown(0);
}
}
// 最小堆的下滤操作,它确保数组中以第 hole 个节点作为根的子树拥有最小堆性质
template <typename _UData>
void HeapTimerContainer<_UData>::percolateDown(int hole) {
if(_size == 0) return ;
HeapTimer<_UData>* temp = _array[hole];
int child = 0;
for(; ((hole * 2 + 1) <= _size - 1 ); hole = child) {
child = hole * 2 + 1;
if((child < (_size - 1)) && (_array[child + 1]->getExpire() < _array[child]->getExpire())) {
child++;
}
if(_array[child]->getExpire() < temp->getExpire()) {
_array[hole] = _array[child];
_array[hole]->setPos(hole);
} else {
break;
}
}
_array[hole] = temp;
_array[hole]->setPos(hole);
}
template <typename _UData>
void HeapTimerContainer<_UData>::percolateUp(int hole) {
int parent = 0;
HeapTimer<_UData>* temp = _array[hole];
for(; hole > 0; hole = parent) {
parent = (hole - 1) / 2;
if(_array[parent]->getExpire() <= temp->getExpire()) {
break;
}
_array[hole] = _array[parent];
_array[hole]->setPos(hole);
}
_array[hole] = temp;
_array[hole]->setPos(hole);
}
// 将数组的容量扩大一倍
template <typename _UData>
void HeapTimerContainer<_UData>::resize() {
HeapTimer<_UData>** temp = new HeapTimer<_UData>* [2 * _capacity];
_capacity = 2 * _capacity;
for(int i = 0; i < _size; i++) {
temp[i] = _array[i];
}
for(int i = _size; i < _capacity; i++) {
temp[i] = nullptr;
}
delete []_array;
_array = temp;
}
template <typename _UData>
bool HeapTimerContainer<_UData>::isEmpty() {
return _size == 0;
}
#endif