Skip to main content

libuv/handles/
idle.rs

1use crate::{FromInner, HandleTrait, Inner, IntoInner};
2use std::convert::TryFrom;
3use uv::{uv_idle_init, uv_idle_start, uv_idle_stop, uv_idle_t};
4
5callbacks! {
6    pub IdleCB(handle: IdleHandle);
7}
8
9/// Additional data stored on the handle
10#[derive(Default)]
11pub(crate) struct IdleDataFields<'a> {
12    idle_cb: IdleCB<'a>,
13}
14
15/// Callback for uv_idle_start
16extern "C" fn uv_idle_cb(handle: *mut uv_idle_t) {
17    let dataptr = crate::Handle::get_data(uv_handle!(handle));
18    if !dataptr.is_null() {
19        unsafe {
20            if let super::IdleData(d) = &mut (*dataptr).addl {
21                d.idle_cb.call(handle.into_inner());
22            }
23        }
24    }
25}
26
27/// Idle handles will run the given callback once per loop iteration, right before the uv_prepare_t
28/// handles.
29///
30/// Note: The notable difference with prepare handles is that when there are active idle handles,
31/// the loop will perform a zero timeout poll instead of blocking for i/o.
32///
33/// Warning: Despite the name, idle handles will get their callbacks called on every loop
34/// iteration, not when the loop is actually “idle”.
35#[derive(Clone, Copy)]
36pub struct IdleHandle {
37    handle: *mut uv_idle_t,
38}
39
40impl IdleHandle {
41    /// Create and initialize a new idle handle
42    pub fn new(r#loop: &crate::Loop) -> crate::Result<IdleHandle> {
43        let layout = std::alloc::Layout::new::<uv_idle_t>();
44        let handle = unsafe { std::alloc::alloc(layout) as *mut uv_idle_t };
45        if handle.is_null() {
46            return Err(crate::Error::ENOMEM);
47        }
48
49        let ret = unsafe { uv_idle_init(r#loop.into_inner(), handle) };
50        if ret < 0 {
51            unsafe { std::alloc::dealloc(handle as _, layout) };
52            return Err(crate::Error::from_inner(ret as uv::uv_errno_t));
53        }
54
55        crate::Handle::initialize_data(uv_handle!(handle), super::IdleData(Default::default()));
56
57        Ok(IdleHandle { handle })
58    }
59
60    /// Start the handle with the given callback. This function always succeeds, except when cb is
61    /// ().
62    pub fn start<CB: Into<IdleCB<'static>>>(&mut self, cb: CB) -> crate::Result<()> {
63        // uv_cb is either Some(uv_idle_cb) or None
64        let cb = cb.into();
65        let uv_cb = use_c_callback!(uv_idle_cb, cb);
66
67        // cb is either Some(closure) or None - it is saved into data
68        let dataptr = crate::Handle::get_data(uv_handle!(self.handle));
69        if !dataptr.is_null() {
70            if let super::IdleData(d) = unsafe { &mut (*dataptr).addl } {
71                d.idle_cb = cb;
72            }
73        }
74
75        crate::uvret(unsafe { uv_idle_start(self.handle, uv_cb) })
76    }
77
78    /// Stop the handle, the callback will no longer be called. This function always succeeds.
79    pub fn stop(&mut self) -> crate::Result<()> {
80        crate::uvret(unsafe { uv_idle_stop(self.handle) })
81    }
82}
83
84impl FromInner<*mut uv_idle_t> for IdleHandle {
85    fn from_inner(handle: *mut uv_idle_t) -> IdleHandle {
86        IdleHandle { handle }
87    }
88}
89
90impl Inner<*mut uv::uv_handle_t> for IdleHandle {
91    fn inner(&self) -> *mut uv::uv_handle_t {
92        uv_handle!(self.handle)
93    }
94}
95
96impl From<IdleHandle> for crate::Handle {
97    fn from(idle: IdleHandle) -> crate::Handle {
98        crate::Handle::from_inner(Inner::<*mut uv::uv_handle_t>::inner(&idle))
99    }
100}
101
102impl crate::ToHandle for IdleHandle {
103    fn to_handle(&self) -> crate::Handle {
104        crate::Handle::from_inner(Inner::<*mut uv::uv_handle_t>::inner(self))
105    }
106}
107
108impl TryFrom<crate::Handle> for IdleHandle {
109    type Error = crate::ConversionError;
110
111    fn try_from(handle: crate::Handle) -> Result<Self, Self::Error> {
112        let t = handle.get_type();
113        if t != crate::HandleType::IDLE {
114            Err(crate::ConversionError::new(t, crate::HandleType::IDLE))
115        } else {
116            Ok((handle.inner() as *mut uv_idle_t).into_inner())
117        }
118    }
119}
120
121impl HandleTrait for IdleHandle {}
122
123impl crate::Loop {
124    /// Create and initialize a new idle handle
125    pub fn idle(&self) -> crate::Result<IdleHandle> {
126        IdleHandle::new(self)
127    }
128}