1 /* 2 +----------------------------------------------------------------------+ 3 | Swoole | 4 +----------------------------------------------------------------------+ 5 | This source file is subject to version 2.0 of the Apache license, | 6 | that is bundled with this package in the file LICENSE, and is | 7 | available through the world-wide-web at the following url: | 8 | http://www.apache.org/licenses/LICENSE-2.0.html | 9 | If you did not receive a copy of the Apache2.0 license and are unable| 10 | to obtain it through the world-wide-web, please send a note to | 11 | license@swoole.com so we can mail you a copy immediately. | 12 +----------------------------------------------------------------------+ 13 | Author: Tianfeng Han <mikan.tenny@gmail.com> | 14 | Twosee <twose@qq.com> | 15 +----------------------------------------------------------------------+ 16 */ 17 18 #pragma once 19 20 #include "swoole.h" 21 #include "swoole_heap.h" 22 #include "swoole_reactor.h" 23 24 #include <unordered_map> 25 26 #define SW_TIMER_MIN_MS 1 27 #define SW_TIMER_MIN_SEC 0.001 28 #define SW_TIMER_MAX_MS LONG_MAX 29 #define SW_TIMER_MAX_SEC ((double) LONG_MAX / 1000) 30 31 namespace swoole { 32 33 typedef std::function<void(TimerNode *)> TimerDestructor; 34 35 struct TimerNode { 36 enum Type { 37 TYPE_KERNEL, 38 TYPE_PHP, 39 }; 40 long id; 41 enum Type type; 42 int64_t exec_msec; 43 int64_t interval; 44 uint64_t exec_count; 45 uint64_t round; 46 bool removed; 47 HeapNode *heap_node; 48 TimerCallback callback; 49 void *data; 50 TimerDestructor destructor; 51 }; 52 53 class Timer { 54 private: 55 /*--------------signal timer--------------*/ 56 Reactor *reactor_ = nullptr; 57 Heap heap; 58 std::unordered_map<long, TimerNode *> map; 59 uint64_t round; 60 long _next_id; 61 long _current_id; 62 /*---------------event timer--------------*/ 63 struct timeval base_time; 64 /*----------------------------------------*/ 65 int (*set)(Timer *timer, long exec_msec) = nullptr; 66 void (*close)(Timer *timer) = nullptr; 67 68 bool init_reactor(Reactor *reactor); 69 bool init_system_timer(); 70 71 public: 72 long next_msec_; 73 74 Timer(); 75 ~Timer(); 76 static int now(struct timeval *time); 77 get_relative_msec()78 inline int64_t get_relative_msec() { 79 struct timeval _now; 80 if (now(&_now) < 0) { 81 return SW_ERR; 82 } 83 int64_t msec1 = (_now.tv_sec - base_time.tv_sec) * 1000; 84 int64_t msec2 = (_now.tv_usec - base_time.tv_usec) / 1000; 85 return msec1 + msec2; 86 } 87 get_absolute_msec()88 inline static int64_t get_absolute_msec() { 89 struct timeval now; 90 if (Timer::now(&now) < 0) { 91 return SW_ERR; 92 } 93 int64_t msec1 = (now.tv_sec) * 1000; 94 int64_t msec2 = (now.tv_usec) / 1000; 95 return msec1 + msec2; 96 } 97 get_reactor()98 inline Reactor *get_reactor() { 99 return reactor_; 100 } 101 102 bool init(); 103 TimerNode *add(long _msec, bool persistent, void *data, const TimerCallback &callback); 104 bool remove(TimerNode *tnode); update(TimerNode * tnode)105 void update(TimerNode *tnode) { 106 heap.change_priority(tnode->exec_msec, tnode->heap_node); 107 } delay(TimerNode * tnode,long delay_ms)108 void delay(TimerNode *tnode, long delay_ms) { 109 long now_ms = get_relative_msec(); 110 tnode->exec_msec = (now_ms < 0 ? tnode->exec_msec : now_ms) + delay_ms; 111 update(tnode); 112 } 113 void reinit(Reactor *reactor); 114 int select(); 115 get(long id)116 inline TimerNode *get(long id) { 117 auto it = map.find(id); 118 if (it == map.end()) { 119 return nullptr; 120 } else { 121 return it->second; 122 } 123 } 124 get(long id,const enum TimerNode::Type type)125 inline TimerNode *get(long id, const enum TimerNode::Type type) { 126 TimerNode *tnode = get(id); 127 return (tnode && tnode->type == type) ? tnode : nullptr; 128 } 129 count()130 inline size_t count() { 131 return map.size(); 132 } 133 get_round()134 inline uint64_t get_round() { 135 return round; 136 } 137 remove(long id)138 inline bool remove(long id) { 139 return remove(get(id)); 140 } 141 get_map()142 inline const std::unordered_map<long, TimerNode *> &get_map() { 143 return map; 144 } 145 }; 146 } // namespace swoole 147