Skip to content

Commit

Permalink
Use integer_atomics feature
Browse files Browse the repository at this point in the history
Rather than using AtomicUsize and AtomicBool fields within
our ForegroundSignals structure, I'm switching this over
to using AtomicU32 and AtomicU8 values instead.
  • Loading branch information
mmstick committed Oct 26, 2017
1 parent 5e2b08a commit e5d3074
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 28 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
@@ -1,6 +1,7 @@
#![allow(unknown_lints)]
#![allow(while_let_on_iterator)]
#![feature(conservative_impl_trait)]
#![feature(integer_atomics)]

extern crate app_dirs;
#[macro_use]
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
@@ -1,6 +1,7 @@
#![allow(unknown_lints)]
#![allow(while_let_on_iterator)]
#![feature(conservative_impl_trait)]
#![feature(integer_atomics)]

// For a performance boost on Linux
// #![feature(alloc_system)]
Expand Down
49 changes: 21 additions & 28 deletions src/shell/pipe_exec/foreground.rs
@@ -1,64 +1,57 @@
//! Contains the logic for enabling foreground management.

use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::atomic::{AtomicU32, AtomicU8, Ordering};

pub(crate) enum BackgroundResult {
Errored,
Status(u8),
}

const REPLIED: u8 = 1;
const ERRORED: u8 = 2;

/// An atomic structure that can safely be shared across threads, which serves to provide
/// communication between the shell and background threads. The `fg` command uses this
/// structure to notify a background thread that it needs to wait for and return
/// the exit status back to the `fg` function.
pub(crate) struct ForegroundSignals {
grab: AtomicUsize, // TODO: Use AtomicU32 when stable
status: AtomicUsize, // TODO: Use AtomicU8 when stable
reply: AtomicBool,
errored: AtomicBool, // TODO: Combine with reply when U8 is stable
grab: AtomicU32,
status: AtomicU8,
reply: AtomicU8,
}

impl ForegroundSignals {
pub(crate) fn new() -> ForegroundSignals {
ForegroundSignals {
grab: AtomicUsize::new(0),
status: AtomicUsize::new(0),
reply: AtomicBool::new(false),
errored: AtomicBool::new(false),
grab: AtomicU32::new(0),
status: AtomicU8::new(0),
reply: AtomicU8::new(0),
}
}

pub(crate) fn signal_to_grab(&self, pid: u32) {
self.grab.store(pid as usize, Ordering::Relaxed);
}
pub(crate) fn signal_to_grab(&self, pid: u32) { self.grab.store(pid, Ordering::Relaxed); }

pub(crate) fn reply_with(&self, status: i8) {
self.grab.store(0, Ordering::Relaxed);
self.status.store(status as usize, Ordering::Relaxed);
self.reply.store(true, Ordering::Relaxed);
self.status.store(status as u8, Ordering::Relaxed);
self.reply.store(REPLIED, Ordering::Relaxed);
}

pub(crate) fn errored(&self) {
self.grab.store(0, Ordering::Relaxed);
self.errored.store(true, Ordering::Relaxed);
self.reply.store(true, Ordering::Relaxed);
self.reply.store(ERRORED, Ordering::Relaxed);
}

pub(crate) fn was_processed(&self) -> Option<BackgroundResult> {
if self.reply.load(Ordering::Relaxed) {
self.reply.store(false, Ordering::Relaxed);
if self.errored.load(Ordering::Relaxed) {
self.errored.store(false, Ordering::Relaxed);
Some(BackgroundResult::Errored)
} else {
Some(BackgroundResult::Status(self.status.load(Ordering::Relaxed) as u8))
}
let reply = self.reply.load(Ordering::Relaxed);
self.reply.store(0, Ordering::Relaxed);
if reply & ERRORED != 0 {
Some(BackgroundResult::Errored)
} else if reply & REPLIED != 0 {
Some(BackgroundResult::Status(self.status.load(Ordering::Relaxed) as u8))
} else {
None
}
}

pub(crate) fn was_grabbed(&self, pid: u32) -> bool {
self.grab.load(Ordering::Relaxed) == pid as usize
}
pub(crate) fn was_grabbed(&self, pid: u32) -> bool { self.grab.load(Ordering::Relaxed) == pid }
}

0 comments on commit e5d3074

Please sign in to comment.