Skip to main content

cyclonedds/
guard_condition.rs

1use crate::Result;
2use crate::entity::Entity;
3use crate::internal::ffi;
4
5/// A manually triggered condition for use with a [`WaitSet`](crate::WaitSet).
6///
7/// A `GuardCondition` allows application code to unblock a waiting
8/// [`WaitSet`](crate::WaitSet) from another thread or in response to an
9/// external event. Set it to `true` to trigger attached waitsets and `false`
10/// to reset it.
11#[derive(Debug)]
12pub struct GuardCondition<'owner> {
13    pub(crate) inner: cyclonedds_sys::dds_entity_t,
14    phantom: std::marker::PhantomData<&'owner dyn Entity>,
15}
16
17impl<'o> GuardCondition<'o> {
18    /// Creates a new `GuardCondition` owned by `owner`.
19    ///
20    /// The guard condition is valid for the lifetime of `owner`.
21    ///
22    /// # Errors
23    ///
24    /// Returns an [`Error`](crate::Error) if the guard condition fails to
25    /// create.
26    ///
27    /// # Examples
28    ///
29    /// ```
30    /// # use cyclonedds::{Domain, Participant};
31    /// # let domain = Domain::default();
32    /// # let participant = Participant::new(&domain)?;
33    /// use cyclonedds::GuardCondition;
34    ///
35    /// let guard_condition = GuardCondition::new(&participant)?;
36    /// # Ok::<_, cyclonedds::Error>(())
37    /// ```
38    pub fn new(owner: &'o dyn Entity) -> Result<Self> {
39        let owner = owner.id().inner;
40        let inner = ffi::dds_create_guardcondition(owner)?;
41        Ok(Self {
42            inner,
43            phantom: std::marker::PhantomData,
44        })
45    }
46
47    /// Sets the triggered state of this guard condition.
48    ///
49    /// Setting to `true` unblocks any [`WaitSet`](crate::WaitSet) this
50    /// condition is attached to. Setting to `false` resets it.
51    ///
52    /// # Errors
53    ///
54    /// Returns an [`Error`](crate::Error) if the condition failed to set.
55    ///
56    /// # Examples
57    ///
58    /// ```
59    /// # use cyclonedds::{Domain, Participant};
60    /// # let domain = Domain::default();
61    /// # let participant = Participant::new(&domain)?;
62    /// use cyclonedds::GuardCondition;
63    ///
64    /// let mut guard_condition = GuardCondition::new(&participant)?;
65    /// guard_condition.set(true)?;
66    /// # Ok::<_, cyclonedds::Error>(())
67    /// ```
68    pub fn set(&mut self, triggered: bool) -> Result<()> {
69        ffi::dds_set_guardcondition(self.inner, triggered)
70    }
71
72    /// Returns the current triggered state without clearing it.
73    ///
74    /// Equivalent to [`read`](GuardCondition::read).
75    ///
76    /// # Errors
77    ///
78    /// Returns an [`Error`](crate::Error) if the condition failed to read.
79    ///
80    /// # Examples
81    ///
82    /// ```
83    /// # use cyclonedds::{Domain, Participant};
84    /// # let domain = Domain::default();
85    /// # let participant = Participant::new(&domain)?;
86    /// use cyclonedds::GuardCondition;
87    ///
88    /// let mut guard = GuardCondition::new(&participant)?;
89    /// guard.set(true)?;
90    /// assert_eq!(guard.peek()?, true);
91    /// # Ok::<_, cyclonedds::Error>(())
92    /// ```
93    pub fn peek(&self) -> Result<bool> {
94        self.read()
95    }
96
97    /// Returns the current triggered state without clearing it.
98    ///
99    /// # Errors
100    ///
101    /// Returns an [`Error`](crate::Error) if the condition failed to read.
102    ///
103    /// # Examples
104    ///
105    /// ```
106    /// # use cyclonedds::{Domain, Participant};
107    /// # let domain = Domain::default();
108    /// # let participant = Participant::new(&domain)?;
109    /// use cyclonedds::GuardCondition;
110    ///
111    /// let mut guard = GuardCondition::new(&participant)?;
112    /// guard.set(true)?;
113    /// assert_eq!(guard.read()?, true);
114    /// // State is preserved after read.
115    /// assert_eq!(guard.read()?, true);
116    /// # Ok::<_, cyclonedds::Error>(())
117    /// ```
118    pub fn read(&self) -> Result<bool> {
119        ffi::dds_read_guardcondition(self.inner)
120    }
121
122    /// Returns the current triggered state and clears it.
123    ///
124    /// Unlike [`read`](GuardCondition::read), this resets the triggered state
125    /// to `false` after returning it.
126    ///
127    /// # Errors
128    ///
129    /// Returns an [`Error`](crate::Error) if the condition failed to take.
130    ///
131    /// # Examples
132    ///
133    /// ```
134    /// # use cyclonedds::{Domain, Participant};
135    /// # let domain = Domain::default();
136    /// # let participant = Participant::new(&domain)?;
137    /// use cyclonedds::GuardCondition;
138    ///
139    /// let mut guard = GuardCondition::new(&participant)?;
140    /// guard.set(true)?;
141    /// assert_eq!(guard.take()?, true);
142    /// // State has been cleared.
143    /// assert_eq!(guard.read()?, false);
144    /// # Ok::<_, cyclonedds::Error>(())
145    /// ```
146    pub fn take(&mut self) -> Result<bool> {
147        ffi::dds_take_guardcondition(self.inner)
148    }
149}
150
151impl Drop for GuardCondition<'_> {
152    fn drop(&mut self) {
153        let result = ffi::dds_delete(self.inner);
154        debug_assert!(
155            result.is_ok(),
156            "unable to delete {self:?}: failed with {result:?}"
157        );
158    }
159}
160
161#[cfg(test)]
162mod tests {
163    use super::*;
164
165    #[test]
166    fn test_guard_condition_create() {
167        let domain_id = crate::tests::domain::unique_id();
168        let domain = crate::Domain::new(domain_id).unwrap();
169        let participant = crate::Participant::new(&domain).unwrap();
170
171        let _ = GuardCondition::new(&participant).unwrap();
172    }
173
174    #[test]
175    fn test_guard_condition_with_invalid_participant() {
176        let domain_id = crate::tests::domain::unique_id();
177        let domain = crate::Domain::new(domain_id).unwrap();
178        let mut participant = crate::Participant::new(&domain).unwrap();
179        let participant_id = participant.inner;
180        participant.inner = 0;
181        let result = GuardCondition::new(&participant).unwrap_err();
182        participant.inner = participant_id;
183
184        assert_eq!(result, crate::Error::BadParameter);
185    }
186
187    #[test]
188    fn test_guard_condition_set() {
189        let domain_id = crate::tests::domain::unique_id();
190        let domain = crate::Domain::new(domain_id).unwrap();
191        let participant = crate::Participant::new(&domain).unwrap();
192        let mut guard_condition = GuardCondition::new(&participant).unwrap();
193
194        guard_condition.set(true).unwrap();
195        guard_condition.set(false).unwrap();
196    }
197
198    #[test]
199    fn test_guard_condition_peek() {
200        let domain_id = crate::tests::domain::unique_id();
201        let domain = crate::Domain::new(domain_id).unwrap();
202        let participant = crate::Participant::new(&domain).unwrap();
203        let mut guard_condition = GuardCondition::new(&participant).unwrap();
204
205        guard_condition.set(true).unwrap();
206        let triggered = guard_condition.peek().unwrap();
207        assert!(triggered);
208        let triggered = guard_condition.peek().unwrap();
209        assert!(triggered);
210
211        guard_condition.set(false).unwrap();
212        let triggered = guard_condition.peek().unwrap();
213        assert!(!triggered);
214        let triggered = guard_condition.peek().unwrap();
215        assert!(!triggered);
216    }
217
218    #[test]
219    fn test_guard_condition_read() {
220        let domain_id = crate::tests::domain::unique_id();
221        let domain = crate::Domain::new(domain_id).unwrap();
222        let participant = crate::Participant::new(&domain).unwrap();
223        let mut guard_condition = GuardCondition::new(&participant).unwrap();
224
225        guard_condition.set(true).unwrap();
226        let triggered = guard_condition.read().unwrap();
227        assert!(triggered);
228        let triggered = guard_condition.read().unwrap();
229        assert!(triggered);
230
231        guard_condition.set(false).unwrap();
232        let triggered = guard_condition.read().unwrap();
233        assert!(!triggered);
234        let triggered = guard_condition.read().unwrap();
235        assert!(!triggered);
236    }
237
238    #[test]
239    fn test_guard_condition_take() {
240        let domain_id = crate::tests::domain::unique_id();
241        let domain = crate::Domain::new(domain_id).unwrap();
242        let participant = crate::Participant::new(&domain).unwrap();
243        let mut guard_condition = GuardCondition::new(&participant).unwrap();
244
245        guard_condition.set(true).unwrap();
246        let triggered = guard_condition.take().unwrap();
247        assert!(triggered);
248        let triggered = guard_condition.take().unwrap();
249        assert!(!triggered);
250
251        guard_condition.set(false).unwrap();
252        let triggered = guard_condition.take().unwrap();
253        assert!(!triggered);
254        let triggered = guard_condition.take().unwrap();
255        assert!(!triggered);
256    }
257
258    #[test]
259    fn test_guard_condition_operations_on_invalid_guard_condition() {
260        let domain_id = crate::tests::domain::unique_id();
261        let domain = crate::Domain::new(domain_id).unwrap();
262        let participant = crate::Participant::new(&domain).unwrap();
263        let mut guard_condition = GuardCondition::new(&participant).unwrap();
264        let guard_condition_id = guard_condition.inner;
265        guard_condition.inner = 0;
266
267        let result = guard_condition.set(false).unwrap_err();
268        assert_eq!(result, crate::Error::BadParameter);
269        let result = guard_condition.read().unwrap_err();
270        assert_eq!(result, crate::Error::BadParameter);
271        let result = guard_condition.take().unwrap_err();
272        assert_eq!(result, crate::Error::BadParameter);
273
274        guard_condition.inner = guard_condition_id;
275    }
276}