Skip to content

Commit

Permalink
Implement Extend and From/IntoIterator for SigSet
Browse files Browse the repository at this point in the history
  • Loading branch information
magicant committed Feb 20, 2022
1 parent 3ea9b7b commit 2196824
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 8 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Expand Up @@ -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

Expand Down
70 changes: 62 additions & 8 deletions src/sys/signal.rs
Expand Up @@ -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)]
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)]
Expand Down Expand Up @@ -1235,6 +1282,13 @@ mod tests {
}).join().unwrap();
}

#[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() {
Expand Down

0 comments on commit 2196824

Please sign in to comment.