1#![allow(non_camel_case_types)]
2#![allow(non_snake_case)]
3#![allow(non_upper_case_globals)]
4#![allow(dead_code)]
5
6use super::*;
7use core::ffi::c_void;
8use crate::common::{self,tsidallocator::TsIdAllocator,tsmap::TsHashMap};
9use std::mem;
10#[cfg(windows)]
11use windows_sys::Win32::Foundation::FILETIME;
12#[cfg(windows)]
13use windows_sys::Win32::System::Threading::{self,TP_CALLBACK_INSTANCE,TP_TIMER};
14
15#[cfg(unix)]
16use libc;
17
18pub type timer_call_back = fn(timer_id:i32,timer_data:usize);
19
20#[cfg(windows)]
21type os_callback_fn = unsafe extern "system" fn(instance: *mut TP_CALLBACK_INSTANCE, context: *mut c_void, timer: *mut TP_TIMER);
22#[cfg(windows)]
23#[no_mangle]
24unsafe extern "system" fn os_timer_callback(_instance: *mut TP_CALLBACK_INSTANCE,
25 context: *mut c_void, _timer: *mut TP_TIMER) {
26 if context.is_null() {
27 return
28 }
29
30 let tid = *(context as *const i32);
31 let t= match get_timer_by_id(tid) {
34 None=>return,
35 Some(t)=>t,
36 };
37 (t.app_callback)(t.timer_id,t.timer_data);
38}
39
40#[cfg(unix)]
41type os_callback_fn = unsafe extern fn(ev:libc::sigval);
42#[cfg(unix)]
43#[no_mangle]
44unsafe extern "C" fn os_timer_callback(ev:libc::sigval) {
45 let tev = &ev;
46 if tev.sival_ptr.is_null() {
47 return
48 }
49 let tid = *(tev.sival_ptr as *const i32);
50 let t= match get_timer_by_id(tid) {
53 None=>return,
54 Some(t)=>t,
55 };
56 (t.app_callback)(t.timer_id,t.timer_data);
57}
58
59#[derive(Clone,Debug)]
60pub struct os_timer_t {
61 dur_msec:u64,
62 timer_data:usize,
63 timer_id:i32,
64 pub(crate) app_callback:timer_call_back,
65 #[cfg(unix)]
66 os_timer_id:libc::timer_t,
67 #[cfg(windows)]
68 os_timer_id:*mut TP_TIMER,
69}
70
71
72impl os_timer_t {
73 pub fn new(dur_msec:u64,timer_data:usize,callbackfn:timer_call_back)->Option<Self> {
74 let tid = match unsafe { &mut gOsTimerAlloc} {
75 None=>return None,
76 Some(a)=>{
77 let id = a.allocate_id();
78 if id==TsIdAllocator::INVALID_ID {
79 return None;
80 }
81 id
82 },
83 };
84 unsafe {
85 gTimerData[tid as usize]=tid;
86 }
87 let os_tid = match unsafe {
88 set_os_timer(dur_msec, std::ptr::addr_of!(gTimerData[tid as usize]) as *mut u8, os_timer_callback)
89 } {
90 None=>return None,
91 Some(t)=>t,
92 };
93
94 let tm = Self {
95 dur_msec:dur_msec,
96 timer_data:timer_data,
97 timer_id:tid,
98 os_timer_id:os_tid,
99 app_callback:callbackfn,
100 };
101 if insert_timer(tid, tm.clone()) != errcode::RESULT_SUCCESS {
102 return None
103 }
104 return Some(tm);
105 }
106
107 pub fn close(&mut self) {
108
109 }
110}
111
112const MAX_OS_TIMER_COUNT:usize = 1024;
113static mut gOsTimerAlloc:Option<TsIdAllocator> = None;
114static mut gOsTimerMap:Option<TsHashMap<i32,os_timer_t>> = None;
115static mut gTimerData:[i32;MAX_OS_TIMER_COUNT+1]=[0;MAX_OS_TIMER_COUNT+1];
116
117pub fn init_os_timer() {
118 unsafe {
119 if gOsTimerAlloc.is_none() {
120 gOsTimerAlloc = Some(TsIdAllocator::new(1, MAX_OS_TIMER_COUNT as i32));
121 }
122 if gOsTimerMap.is_none() {
123 gOsTimerMap = Some(TsHashMap::new(MAX_OS_TIMER_COUNT));
124 }
125 }
126}
127
128fn insert_timer(tid:i32,timer:os_timer_t)->errcode::RESULT {
129 let tm = match unsafe {&mut gOsTimerMap} {
130 None=>return errcode::ERROR_NOT_INITIALIZED,
131 Some(m)=>m,
132 };
133 return tm.insert(tid,timer);
134}
135fn get_timer_by_id(tid:i32)->Option<&'static mut os_timer_t> {
136 let tm = match unsafe {&mut gOsTimerMap} {
137 None=>return None,
138 Some(m)=>m,
139 };
140 let t = tm.get_mut(&tid);
141 return t;
142}
143
144#[cfg(unix)]
145#[link(name = "os_linux", kind = "static")]
146extern "C" {
147 fn c_create_timer(ptr_data:*mut u8,call_back:os_callback_fn,timer_id:*mut libc::timer_t)->i32;
148}
149
150#[cfg(unix)]
151unsafe fn set_os_timer(dur_msec:u64,data_ptr:*mut u8,call_back:os_callback_fn)->Option<libc::timer_t> {
152
153 let mut timer_id=mem::zeroed::<libc::timer_t>();
154 let res = c_create_timer(data_ptr, call_back,&mut timer_id as *mut libc::timer_t);
156 if res<0 {
157 println!("error create time,ret={}",res);
158 return None;
159 }
160
161 let tv_sec = dur_msec as i64 / 1000;
162 let tv_nsec=(dur_msec as i64 % 1000)*1000*1000;
163 let mut its = libc::itimerspec {
164 it_interval:libc::timespec {
165 tv_sec:tv_sec,
166 tv_nsec:tv_nsec,
167 },
168 it_value:libc::timespec {
169 tv_sec:tv_sec,
170 tv_nsec:tv_nsec,
171 },
172 };
173 let res = libc::timer_settime(timer_id,0,&its as *const libc::itimerspec,std::ptr::null_mut());
174 if res<0 {
175 println!("error create time,ret={}",res);
176 }
177
178 return Some(timer_id);
179
180}
181
182
183#[cfg(windows)]
184unsafe fn set_os_timer(dur_msec:u64,pdata:*mut u8,call_back:os_callback_fn)->Option<*mut TP_TIMER> {
185 let timer = Threading::CreateThreadpoolTimer(Some(call_back), pdata as *mut c_void,std::ptr::null());
186 if timer.is_null() {
187 println!("windows set timer failed,err={}",std::io::Error::last_os_error());
188 return None;
189 }
190
191 println!("windows set timer success,timer={:?}",timer);
192 let ftime = FILETIME {
193 dwLowDateTime:0xFFFFFFFF,
194 dwHighDateTime:0xFFFFFFFF,
195 };
196 Threading::SetThreadpoolTimer(timer,std::ptr::addr_of!(ftime),dur_msec as u32,0);
197 return Some(timer);
198}