diff options
Diffstat (limited to 'bindings/rs-timeout/README.md')
| -rw-r--r-- | bindings/rs-timeout/README.md | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/bindings/rs-timeout/README.md b/bindings/rs-timeout/README.md new file mode 100644 index 0000000..642f71e --- /dev/null +++ b/bindings/rs-timeout/README.md @@ -0,0 +1,163 @@ +# bind-rs-timeout + +Rust binding for [timeout](https://github.com/wahern/timeout). + +It mainly includes two modules: `Timeout` and `TimeoutManager`. They respectively represent a timeout instance and a timeout manager. +- `Timeout` is a timeout instance used to set the timeout time and bind the callback function (supporting closures). +- `TimeoutManager` is used to manage timeout instances, update time, and trigger timeouts. + +## Usage + +To use the `Timeout` structure, you need to first create a `Timeout` instance and set the timeout callback function. Then add it to the `TimeoutManager` (ownership transferred to the C-side `TimeoutManager`), continuously update the `TimeoutManager` time, and call the `TimeoutManager::expired_timeouts` method to return the expired `Timeout` and execute the corresponding timeout callback function. + +```rust +let to = Timeout::new(ToType::Default).unwrap(); // onetime type, relative timeout +let to2 = Timeout::new(ToType::INT).unwrap(); // periodic type +let mut tos = TimeoutManager::new(TIMEOUT_mHZ).unwrap(); + +tos.update_time_rel(0); // relative time, tos.now = 0 +tos.add(to, 50); // onetime, expired time = tos.now + 50 +tos.add(to2, 100); // periodic, starting from tos.now, expiring every 100. + +tos.update_time_abs(150); // absolute time, tos.now = 150 + +for to in tos.expired_timeouts() { + match to { + ToR::OneTime(temp) => { + // onetime type, Timeout, do something + // all flag has cleared assert!(to.is_expired()); will error + temp.run_cb(); + } + ToR::Periodic(temp) => { + //periodic type, &Timeout, do something + // assert!(temp.is_periodic()); will work + } + }; +} +``` + +## Timeout + +`Timeout` is a structure representing a timeout instance used to set the timeout time. The structure contains multiple methods for setting the timeout callback function (supporting closures), checking the timeout status, deleting the timeout operation, etc. + +`Timeout` has three types: +- `ToType::INT`: periodic timer, triggered repeatedly at a fixed interval, independent between each trigger, missing a trigger does not affect the next trigger time. +- `ToType::ABS`: one-time timer, triggered once at the specified absolute time. +- `ToType::Default`: one-time timer, triggered once after the specified relative time after adding the timer time point. + +### Method List + +The following is a list of methods for the `Timeout` structure: + +- `new(flags: ToType) -> Result<Timeout, &'static str>`: Create a new `Timeout` instance and set the timeout flag. +- `is_pending(&self) -> bool`: Check whether the timeout has been registered and is on the timing wheel. +- `is_expired(&self) -> bool`: Check whether the timeout has been registered and is on the expiration queue. +- `is_periodic(&self) -> bool`: Check whether the timeout is periodic. +- `delete(&mut self)`: Delete the timeout from the timing wheel or expiration queue. +- `set_cb<T>(&mut self, cb: TimeoutCallBack<T>)`: Set the timeout callback function. +- `set_cb_closure<F>(&mut self, closure: &mut F) where F: FnMut()`: Pass in a closure to set the timeout callback. +- `run_cb(&self) -> bool`: Run the timeout callback function and return whether it has been executed successfully. + +### Adding Callbacks + +`Timeout` supports adding callbacks, which will be called by `run_cb` after expiration. + +The callback function of `Timeout` supports passing in C-compatible functions and `FnMut()` type closures. +- When passing in a function, the function parameter is of type `&mut T`, and the return value is `()`. +- When passing in a closure, the input parameter is `()`, and the return value is `()`. + +```rust +pub struct Session { pub session_id: String,} +let mut timeout = Timeout::new(ToType::Default).unwrap(); + +extern "C" fn rust_callback(arg: &mut i32) { + println!("Callback executed with arg: {}", arg); +} + +let mut binding = 11; +let cb = TimeoutCallBack::new(rust_callback, &mut binding); + +timeout.set_cb(cb); +timeout.run_cb(); + +let mut session = Session { session_id: "123".to_string(),}; + +timeout.set_cb_closure(&mut || { + println!("Callback executed with session_id: {}", session.session_id); + session.session_id = "456".to_string(); + println!("Callback executed with session_id: {}", session.session_id); +}); + +timeout.run_cb(); +``` + +Please note the lifetime of the callback. +- When passing in a function, it is necessary to ensure that the lifetime of the function and its parameters is longer than the lifetime of `Timeout`, otherwise calling it will return false, indicating that the call failed. +- When passing in a closure, it is necessary to ensure that the lifetime of the closure and its calling variables is longer than the lifetime of `Timeout`, otherwise calling it will return false, indicating that the call failed. + +## TimeoutManager + +`TimeoutManager` provides a `TimeoutManager` structure used to manage timeout operations. The structure contains multiple methods for creating, adding, deleting, and updating timeout operations. + +### Method List + +The following is a list of methods for the `TimeoutManager` structure: + +- `new(hz_set: timeout_t) -> Result<TimeoutManager, &'static str>`: Create a new `TimeoutManager` instance. +- `close(&mut self)`: Close the `TimeoutManager` instance. +- `update_time_rel(&mut self, time: timeout_t)`: Update the time, now = now + relative time. +- `update_time_abs(&mut self, current_time: timeout_t)`: Update the time, now = absolute time. +- `get_hz(&self) -> timeout_t`: Get the frequency of `TimeoutManager`. +- `get_next_wait_time(&self) -> timeout_t`: Get the waiting time before the next timeout expires (definitely less than the actual waiting time). Returns `u64::MAX` if there is no waiting time. +- `any_pending(&self) -> bool`: Check whether any timeout is waiting. +- `any_expired(&self) -> bool`: Check whether any timeout has expired. +- `check(&self) -> bool`: Check whether `TimeoutManager` is valid. + +Methods related to `Timeout`: + +- `add(&mut self, to: Timeout, timeout: timeout_t)`: Add a timeout, and transfer ownership to the C-side `TimeoutManager`. Depending on the type of the `to` parameter, the `timeout` parameter will have different effects. + - For the `ToType::INT` type, the `timeout` parameter is the periodic interval time. The start time is the current time of `TimeoutManager`. + - For the `ToType::ABS` type, it is triggered once at the specified absolute time. + - For the `ToType::Default` type, it is triggered once after the specified relative time after adding the timer time point. +- `delete(&mut self, to: &mut Timeout)`: Delete the timeout. +- `expired_timeouts(&mut self) -> ExpireIter`: Get the expired timeouts and return an iterator. + - For the corresponding `Timeout`, two types are returned: `ToR::OneTime` and `ToR::Periodic`. + - For non-periodic `Timeout`, the returned type is `Timeout`, and ownership is transferred to Rust. + - For periodic `Timeout`, its ownership is still on the C-side, so `&Timeout` type is returned. +- `next_timeouts_pending(&mut self) -> NextIter`: Get the waiting `&Timeout` and return an iterator. +- `next_timeouts_expired(&mut self) -> NextIter`: Get the expired `&Timeout` and return an iterator. +- `next_timeouts_all(&mut self) -> NextIter`: Get all `&Timeout` and return an iterator. + +Note: `next_timeouts_xxx` is only a query method and does not perform any operations on the waiting or expired queues. + +Simple example + +```rust +xxx +let mut tos = TimeoutManager::new(TIMEOUT_mHZ).unwrap(); +xxx + +for to in tos.expired_timeouts() { + match to { + ToR::OneTime(temp) => { + // onetime type, Timeout, do something + temp.run_cb(); + } + ToR::Periodic(temp) => { + //periodic type, &Timeout, do something + // temp.run_cb(); + } + }; +} + +for to_ptr in tos.next_timeouts_expired() { + // do something + to_ptr.run_cb(); +} +``` + +## Others + +For periodic `Timeout`, its ownership is on the C side from the beginning of adding to `TimeoutManager` until `TimeoutManager` is closed. Therefore, the ownership of periodic `Timeout` cannot be obtained on the Rust side, only its reference can be obtained. + +A separate `delete_to_periodic(to: &Timeout)` is provided to remove periodic `Timeout` from `TimeoutManager`.
\ No newline at end of file |
