Skip to content

Commit b0a39cb

Browse files
bors[bot]magicant
andauthored
Merge #1553
1553: Implement Extend and From/IntoIterator for SigSet r=rtzoeller a=magicant Co-authored-by: WATANABE Yuki <[email protected]>
2 parents 3ea9b7b + 2196824 commit b0a39cb

File tree

2 files changed

+69
-8
lines changed

2 files changed

+69
-8
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,19 @@ This project adheres to [Semantic Versioning](https://semver.org/).
4747
(#[1557](https://github.com/nix-rust/nix/pull/1557))
4848
- Added `nix::uncontext` module on s390x.
4949
(#[1662](https://github.com/nix-rust/nix/pull/1662))
50+
- Implemented `Extend`, `FromIterator`, and `IntoIterator` for `SigSet` and
51+
added `SigSet::iter` and `SigSetIter`.
52+
(#[1553](https://github.com/nix-rust/nix/pull/1553))
5053

5154
### Changed
5255

5356
- `mqueue` functions now operate on a distinct type, `nix::mqueue::MqdT`.
5457
Accessors take this type by reference, not by value.
5558
(#[1639](https://github.com/nix-rust/nix/pull/1639))
59+
- Removed `SigSet::extend` in favor of `<SigSet as Extend<Signal>>::extend`.
60+
Because of this change, you now need `use std::iter::Extend` to call `extend`
61+
on a `SigSet`.
62+
(#[1553](https://github.com/nix-rust/nix/pull/1553))
5663

5764
### Fixed
5865

src/sys/signal.rs

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,9 @@ feature! {
482482
#![feature = "signal"]
483483

484484
use crate::unistd::Pid;
485+
use std::iter::Extend;
486+
use std::iter::FromIterator;
487+
use std::iter::IntoIterator;
485488

486489
/// Specifies a set of [`Signal`]s that may be blocked, waited for, etc.
487490
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
@@ -532,14 +535,9 @@ impl SigSet {
532535
}
533536
}
534537

535-
/// Merge all of `other`'s signals into this set.
536-
// TODO: use libc::sigorset on supported operating systems.
537-
pub fn extend(&mut self, other: &SigSet) {
538-
for signal in Signal::iterator() {
539-
if other.contains(signal) {
540-
self.add(signal);
541-
}
542-
}
538+
/// Returns an iterator that yields the signals contained in this set.
539+
pub fn iter(&self) -> SigSetIter<'_> {
540+
self.into_iter()
543541
}
544542

545543
/// Gets the currently blocked (masked) set of signals for the calling thread.
@@ -593,6 +591,55 @@ impl AsRef<libc::sigset_t> for SigSet {
593591
}
594592
}
595593

594+
// TODO: Consider specialization for the case where T is &SigSet and libc::sigorset is available.
595+
impl Extend<Signal> for SigSet {
596+
fn extend<T>(&mut self, iter: T)
597+
where T: IntoIterator<Item = Signal> {
598+
for signal in iter {
599+
self.add(signal);
600+
}
601+
}
602+
}
603+
604+
impl FromIterator<Signal> for SigSet {
605+
fn from_iter<T>(iter: T) -> Self
606+
where T: IntoIterator<Item = Signal> {
607+
let mut sigset = SigSet::empty();
608+
sigset.extend(iter);
609+
sigset
610+
}
611+
}
612+
613+
/// Iterator for a [`SigSet`].
614+
///
615+
/// Call [`SigSet::iter`] to create an iterator.
616+
#[derive(Clone, Debug)]
617+
pub struct SigSetIter<'a> {
618+
sigset: &'a SigSet,
619+
inner: SignalIterator,
620+
}
621+
622+
impl Iterator for SigSetIter<'_> {
623+
type Item = Signal;
624+
fn next(&mut self) -> Option<Signal> {
625+
loop {
626+
match self.inner.next() {
627+
None => return None,
628+
Some(signal) if self.sigset.contains(signal) => return Some(signal),
629+
Some(_signal) => continue,
630+
}
631+
}
632+
}
633+
}
634+
635+
impl<'a> IntoIterator for &'a SigSet {
636+
type Item = Signal;
637+
type IntoIter = SigSetIter<'a>;
638+
fn into_iter(self) -> Self::IntoIter {
639+
SigSetIter { sigset: self, inner: Signal::iterator() }
640+
}
641+
}
642+
596643
/// A signal handler.
597644
#[allow(unknown_lints)]
598645
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
@@ -1235,6 +1282,13 @@ mod tests {
12351282
}).join().unwrap();
12361283
}
12371284

1285+
#[test]
1286+
fn test_from_and_into_iterator() {
1287+
let sigset = SigSet::from_iter(vec![Signal::SIGUSR1, Signal::SIGUSR2]);
1288+
let signals = sigset.into_iter().collect::<Vec<Signal>>();
1289+
assert_eq!(signals, [Signal::SIGUSR1, Signal::SIGUSR2]);
1290+
}
1291+
12381292
#[test]
12391293
#[cfg(not(target_os = "redox"))]
12401294
fn test_sigaction() {

0 commit comments

Comments
 (0)