summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md7
-rw-r--r--src/sys/signal.rs70
2 files changed, 69 insertions, 8 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 765ab11a..942d7b3d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -47,12 +47,19 @@ This project adheres to [Semantic Versioning](https://semver.org/).
(#[1557](https://github.com/nix-rust/nix/pull/1557))
- Added `nix::uncontext` module on s390x.
(#[1662](https://github.com/nix-rust/nix/pull/1662))
+- Implemented `Extend`, `FromIterator`, and `IntoIterator` for `SigSet` and
+ added `SigSet::iter` and `SigSetIter`.
+ (#[1553](https://github.com/nix-rust/nix/pull/1553))
### Changed
- `mqueue` functions now operate on a distinct type, `nix::mqueue::MqdT`.
Accessors take this type by reference, not by value.
(#[1639](https://github.com/nix-rust/nix/pull/1639))
+- Removed `SigSet::extend` in favor of `<SigSet as Extend<Signal>>::extend`.
+ Because of this change, you now need `use std::iter::Extend` to call `extend`
+ on a `SigSet`.
+ (#[1553](https://github.com/nix-rust/nix/pull/1553))
### Fixed
diff --git a/src/sys/signal.rs b/src/sys/signal.rs
index ddc02483..f10a2133 100644
--- a/src/sys/signal.rs
+++ b/src/sys/signal.rs
@@ -482,6 +482,9 @@ feature! {
#![feature = "signal"]
use crate::unistd::Pid;
+use std::iter::Extend;
+use std::iter::FromIterator;
+use std::iter::IntoIterator;
/// Specifies a set of [`Signal`]s that may be blocked, waited for, etc.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
@@ -532,14 +535,9 @@ impl SigSet {
}
}
- /// Merge all of `other`'s signals into this set.
- // TODO: use libc::sigorset on supported operating systems.
- pub fn extend(&mut self, other: &SigSet) {
- for signal in Signal::iterator() {
- if other.contains(signal) {
- self.add(signal);
- }
- }
+ /// Returns an iterator that yields the signals contained in this set.
+ pub fn iter(&self) -> SigSetIter<'_> {
+ self.into_iter()
}
/// Gets the currently blocked (masked) set of signals for the calling thread.
@@ -593,6 +591,55 @@ impl AsRef<libc::sigset_t> for SigSet {
}
}
+// TODO: Consider specialization for the case where T is &SigSet and libc::sigorset is available.
+impl Extend<Signal> for SigSet {
+ fn extend<T>(&mut self, iter: T)
+ where T: IntoIterator<Item = Signal> {
+ for signal in iter {
+ self.add(signal);
+ }
+ }
+}
+
+impl FromIterator<Signal> for SigSet {
+ fn from_iter<T>(iter: T) -> Self
+ where T: IntoIterator<Item = Signal> {
+ let mut sigset = SigSet::empty();
+ sigset.extend(iter);
+ sigset
+ }
+}
+
+/// Iterator for a [`SigSet`].
+///
+/// Call [`SigSet::iter`] to create an iterator.
+#[derive(Clone, Debug)]
+pub struct SigSetIter<'a> {
+ sigset: &'a SigSet,
+ inner: SignalIterator,
+}
+
+impl Iterator for SigSetIter<'_> {
+ type Item = Signal;
+ fn next(&mut self) -> Option<Signal> {
+ loop {
+ match self.inner.next() {
+ None => return None,
+ Some(signal) if self.sigset.contains(signal) => return Some(signal),
+ Some(_signal) => continue,
+ }
+ }
+ }
+}
+
+impl<'a> IntoIterator for &'a SigSet {
+ type Item = Signal;
+ type IntoIter = SigSetIter<'a>;
+ fn into_iter(self) -> Self::IntoIter {
+ SigSetIter { sigset: self, inner: Signal::iterator() }
+ }
+}
+
/// A signal handler.
#[allow(unknown_lints)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
@@ -1236,6 +1283,13 @@ mod tests {
}
#[test]
+ fn test_from_and_into_iterator() {
+ let sigset = SigSet::from_iter(vec![Signal::SIGUSR1, Signal::SIGUSR2]);
+ let signals = sigset.into_iter().collect::<Vec<Signal>>();
+ assert_eq!(signals, [Signal::SIGUSR1, Signal::SIGUSR2]);
+ }
+
+ #[test]
#[cfg(not(target_os = "redox"))]
fn test_sigaction() {
thread::spawn(|| {