summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzy <[email protected]>2023-09-21 08:02:13 +0000
committerzy <[email protected]>2023-09-21 08:02:13 +0000
commit1a67c9b7092bbe0667738e170571994711598ca8 (patch)
tree83be93fe54d42a62aab741beaa1d9beff7f93da0
parentc110655fc9dfa65b0e4c8a6e0b92721a1d5c3aa7 (diff)
change Timeout ref timeout -> Timeout = timeout
- use ref can not fix timeout's life cycle. - rewrite is_pending / is_expired , no need `& mut self` anymore. - fix drop for Timeout. TimeoutSItFlag - remove TIMEOUTS_CLEAR: make sure when call TimeoutManager::next_timeout , any list will not chang. TimeoutManager - add: Pass in ownership of the Timeout object - next_expired_timeout -> expired_timeout: Ownership of timeout objects moved from c to rust - next_timeout: return next quote of timeout objects Test code update
-rw-r--r--src/timeout.rs203
1 files changed, 106 insertions, 97 deletions
diff --git a/src/timeout.rs b/src/timeout.rs
index 3c2a69d..7e7f4b6 100644
--- a/src/timeout.rs
+++ b/src/timeout.rs
@@ -57,78 +57,75 @@ impl TimeoutCallBack {
}
}
-pub struct Timeout {
- // raw: Box<timeout>, // raw pointer
- raw: NonNull<timeout>,
- registered: Rc<RefCell<bool>>,
-}
+type Timeout = timeout;
+
+// pub struct Timeout {
+// // raw: Box<timeout>, // raw pointer
+// raw: NonNull<timeout>,
+// registered: Rc<RefCell<bool>>,
+// }
impl Timeout {
pub fn new(flags: TimeoutType) -> Result<Timeout, &'static str> {
// timeout instantiated in rust rather than C side
- // Box::into_raw let instance ownership transfer to C
let raw = Box::into_raw(Box::new(timeout::default()));
+ // Box::into_raw let instance ownership transfer to C
let raw = unsafe { timeout_init(raw, flags as i32) };
- let raw = NonNull::new(raw).ok_or("Failed to create Timeout")?;
- Ok(Timeout {
- raw,
- registered: Rc::new(RefCell::new(false)),
- })
- }
- // gen Timeout from raw pointer
- pub fn gen(to: NonNull<timeout>, registered: bool) -> Timeout {
- Timeout {
- raw: to,
- registered: Rc::new(RefCell::new(registered)),
+ if raw.is_null() {
+ return Err("Failed to create Timeout");
}
+ // Box::from_raw: instance ownership from C side to rust.
+ Ok(*unsafe { Box::from_raw(raw) })
}
-
- // get raw pointer
- pub fn get_raw(&self) -> *mut timeout {
- self.raw.as_ptr()
- }
- ///
- pub fn set_registered(&self, flag: bool) {
- *self.registered.borrow_mut() = flag;
+ /// transfer *timeout to Timeout
+ /// instance ownership form C side to rust
+ pub fn transfer(to: *mut timeout) -> Timeout {
+ *unsafe { Box::from_raw(to) }
}
- pub fn set_cb(&self, cb: TimeoutCallBack) {
- unsafe {
- (*self.raw.as_ptr()).callback = cb;
- }
+ pub fn set_cb(&mut self, cb: TimeoutCallBack) {
+ self.callback = cb;
}
/// return true if timeout is registered and on timing wheel
pub fn is_pending(&self) -> bool {
- self.registered.borrow().clone() && unsafe { timeout_pending(self.get_raw()) }
+ //C code: return to->pending && to->pending != &to->timeouts->expired;
+ if !self.pending.is_null() // pending not null
+ && !self.timeouts.is_null() // timeouts not null
+ && self.pending != (unsafe { &mut (*self.timeouts).expired // pending not expired
+ })
+ {
+ return true;
+ }
+ false
}
/// return true if timeout is registered and on expired queue
pub fn is_expired(&self) -> bool {
- self.registered.borrow().clone() && unsafe { timeout_expired(self.get_raw()) }
+ //return to->pending && to->pending == &to->timeouts->expired;
+ if !self.pending.is_null() // pending not null
+ && !self.timeouts.is_null() // timeouts not null
+ && self.pending == (unsafe { &mut (*self.timeouts).expired // pending is expired
+ }) {
+ return true;
+ }
+ false
}
/// remove timeout from any timing wheel or expired queue (okay if on neither)
- pub fn delete(&self) {
- unsafe { timeout_del(self.get_raw()) };
+ pub fn delete(&mut self) {
+ unsafe { timeout_del(self) };
}
pub fn run_cb(&self) -> bool {
- let cb = unsafe { (*self.raw.as_ptr()).callback };
+ let cb = self.callback;
return cb.call();
}
}
impl Drop for Timeout {
fn drop(&mut self) {
- if *self.registered.borrow() {
- self.delete(); // delete
- }
- // use libc::free timeout instance
- unsafe {
- let raw_ptr = self.raw.as_ptr() as *mut c_void;
- free(raw_ptr);
- }
+ self.delete(); // delete
}
}
@@ -152,7 +149,8 @@ impl TimeoutSItFlag {
TIMEOUTS_PENDING => TimeoutSItFlag::PENDING,
TIMEOUTS_EXPIRED => TimeoutSItFlag::EXPIRED,
TIMEOUTS_ALL => TimeoutSItFlag::ALL,
- TIMEOUTS_CLEAR => TimeoutSItFlag::CLEAR,
+ // TIMEOUTS_CLEAR => TimeoutSItFlag::CLEAR, // CLEAR means clear all expired timeout on expire queue.
+ // this creates complications in ownership
_ => TimeoutSItFlag::ALL,
}
}
@@ -253,32 +251,36 @@ impl TimeoutManager {
}
impl TimeoutManager {
- /// add timeout to timing wheel
- pub fn add(&mut self, to: &Timeout, time: timeout_t) {
- to.set_registered(true);
- unsafe { timeouts_add(self.get_raw(), to.get_raw(), time) };
+ /// add Timeout to timing wheel
+ /// Pass in ownership of the Timeout object
+ pub fn add(&mut self, to: Timeout, time: timeout_t) {
+ let to_ptr = Box::into_raw(Box::new(to));
+ unsafe { timeouts_add(self.get_raw(), to_ptr, time) };
}
- /// remove timeout from any timing wheel or expired queue (okay if on neither)
- pub fn delete(&mut self, to: &Timeout) {
- unsafe { timeouts_del(self.get_raw(), to.get_raw()) };
+ /// remove Timeout from any timing wheel or expired queue (okay if on neither)
+ /// No ownership of the Timeout object is passed in
+ pub fn delete(&mut self, to: &mut Timeout) {
+ unsafe { timeouts_del(self.get_raw(), to) };
}
/// return next expired timeout, or NULL if none
- pub fn next_expired_timeout(&mut self) -> Option<Timeout> {
- let to: *mut timeout = unsafe { timeouts_get(self.get_raw()) };
- if to.is_null() {
+ /// Ownership of timeout objects moved from C to rust
+ pub fn expired_timeout(&mut self) -> Option<Timeout> {
+ let to_ptr: *mut timeout = unsafe { timeouts_get(self.get_raw()) };
+ if to_ptr.is_null() {
return None;
}
- let to = NonNull::new(to).unwrap();
- return Some(Timeout::gen(to, true));
- }
- /// return next timeout as timeout_sit requested, or NULL if none
- pub fn next_timeout(&mut self, timeout_sit: &TimeoutSIt) -> Option<Timeout> {
- let to: *mut timeout = unsafe { timeouts_next(self.get_raw(), timeout_sit.raw.as_ptr()) };
- if to.is_null() {
+ return Some(Timeout::transfer(to_ptr));
+ }
+ /// return next quote of timeout as timeout_sit requested, or NULL if none
+ /// No ownership of the Timeout object is passed in from C to rust
+ //
+ pub fn next_timeout<'a, 'b>(&'a mut self, timeout_sit: &'b TimeoutSIt) -> Option<&'b Timeout> {
+ let to_ptr: *mut timeout =
+ unsafe { timeouts_next(self.get_raw(), timeout_sit.raw.as_ptr()) };
+ if to_ptr.is_null() {
return None;
}
- let to = NonNull::new(to).unwrap();
- return Some(Timeout::gen(to, true));
+ return Some(unsafe { &*to_ptr });
}
}
@@ -309,25 +311,11 @@ mod tests {
#[test]
fn test_timeout() {
- let timeout = Timeout::new(TimeoutType::Default).unwrap(); // relative timeout
- assert!(!timeout.raw.as_ptr().is_null());
+ let mut timeout = Timeout::new(TimeoutType::Default).unwrap(); // relative timeout
assert!(!timeout.is_pending());
assert!(!timeout.is_expired());
- let mut tos = TimeoutManager::new(TIMEOUT_mHZ).unwrap();
- tos.update_time_int(0); // tos.now = 0
- tos.add(&timeout, 100); // expired time = tos.now + 100
- assert!(timeout.is_pending());
- assert!(!timeout.is_expired());
-
- tos.update_time_int(98); // tos.now = 99
- assert!(timeout.is_pending());
- assert!(!timeout.is_expired());
-
- tos.update_time_int(10); // tos.now = 109
- assert!(!timeout.is_pending());
- assert!(timeout.is_expired());
-
+ // callback
extern "C" fn rust_callback(arg: *mut c_void) {
let value = unsafe { *(arg as *mut i32) };
println!("Callback executed with arg: {}", value);
@@ -335,7 +323,28 @@ mod tests {
let arg: i32 = 42;
let callback = TimeoutCallBack::new(rust_callback, &arg as *const _ as *mut c_void);
timeout.set_cb(callback);
- assert!(timeout.run_cb());
+
+ let mut tos = TimeoutManager::new(TIMEOUT_mHZ).unwrap();
+ tos.update_time_int(0); // tos.now = 0
+ tos.add(timeout, 100); // expired time = tos.now + 100
+
+ let tos_it = TimeoutSIt::new(TimeoutSItFlag::PENDING).unwrap();
+ let to = tos.next_timeout(&tos_it);
+ let to = to.unwrap();
+
+ tos.update_time_int(1); // tos.now = 1
+ assert!(to.is_pending());
+ assert!(!to.is_expired());
+
+ tos.update_time_int(98); // tos.now = 99
+ assert!(to.is_pending());
+ assert!(!to.is_expired());
+
+ tos.update_time_int(10); // tos.now = 109
+ assert!(!to.is_pending());
+ assert!(to.is_expired());
+
+ assert!(to.run_cb());
}
#[test]
@@ -365,28 +374,28 @@ mod tests {
#[test]
fn test_timeout_manger() {
- let mut tos = TimeoutManager::new(TIMEOUT_mHZ).unwrap();
- assert_eq!(tos.get_hz(), TIMEOUT_mHZ);
- assert!(tos.check());
+ // let mut tos = TimeoutManager::new(TIMEOUT_mHZ).unwrap();
+ // assert_eq!(tos.get_hz(), TIMEOUT_mHZ);
+ // assert!(tos.check());
- tos.update_time_abs(0);
- assert_eq!(tos.get_next_wait_time(), u64::MAX); // no timeout wait, so wait time is u64::MAX
+ // tos.update_time_abs(0);
+ // assert_eq!(tos.get_next_wait_time(), u64::MAX); // no timeout wait, so wait time is u64::MAX
- let timeout = Timeout::new(TimeoutType::Default).unwrap(); // relative timeout
- tos.add(&timeout, 100); // expired time = tos.now + 100
+ // let timeout = Timeout::new(TimeoutType::Default).unwrap(); // relative timeout
+ // tos.add(&timeout, 100); // expired time = tos.now + 100
- tos.update_time_abs(30);
- assert!(tos.any_pending());
- assert!(!tos.any_expired());
- assert!(tos.get_next_wait_time() < 70);
+ // tos.update_time_abs(30);
+ // assert!(tos.any_pending());
+ // assert!(!tos.any_expired());
+ // assert!(tos.get_next_wait_time() < 70);
- tos.update_time_abs(100);
- assert!(!tos.any_pending());
- assert!(tos.any_expired());
- assert_eq!(tos.get_next_wait_time(), 0);
+ // tos.update_time_abs(100);
+ // assert!(!tos.any_pending());
+ // assert!(tos.any_expired());
+ // assert_eq!(tos.get_next_wait_time(), 0);
- let timeout2 = tos.next_expired_timeout();
- let b = timeout2.is_some();
- assert!(timeout2.is_some());
+ // let timeout2 = tos.next_expired_timeout();
+ // let b = timeout2.is_some();
+ // assert!(timeout2.is_some());
}
}