diff options
| author | Aaron Turon <aturon@mozilla.com> | 2014-10-15 15:45:59 -0700 |
|---|---|---|
| committer | Aaron Turon <aturon@mozilla.com> | 2014-11-08 20:40:38 -0800 |
| commit | 3d195482a45bf3ed0f12dc9d70d14192262ca711 (patch) | |
| tree | d9cf1a93cc1e862e641cd17fdb41ebe93d22bfea /src/libnative | |
| parent | d34b1b0ca9bf5e0d7cd30952f5de0ab09ed57b41 (diff) | |
| download | rust-3d195482a45bf3ed0f12dc9d70d14192262ca711.tar.gz rust-3d195482a45bf3ed0f12dc9d70d14192262ca711.zip | |
Runtime removal: refactor helper threads
This patch continues the runtime removal by moving libnative::io::helper_thread into sys::helper_signal and sys_common::helper_thread Because this eliminates APIs in `libnative` and `librustrt`, it is a: [breaking-change] This functionality is likely to be available publicly, in some form, from `std` in the future.
Diffstat (limited to 'src/libnative')
| -rw-r--r-- | src/libnative/io/helper_thread.rs | 197 | ||||
| -rw-r--r-- | src/libnative/io/mod.rs | 2 |
2 files changed, 0 insertions, 199 deletions
diff --git a/src/libnative/io/helper_thread.rs b/src/libnative/io/helper_thread.rs deleted file mode 100644 index d1368ad31f4..00000000000 --- a/src/libnative/io/helper_thread.rs +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Implementation of the helper thread for the timer module -//! -//! This module contains the management necessary for the timer worker thread. -//! This thread is responsible for performing the send()s on channels for timers -//! that are using channels instead of a blocking call. -//! -//! The timer thread is lazily initialized, and it's shut down via the -//! `shutdown` function provided. It must be maintained as an invariant that -//! `shutdown` is only called when the entire program is finished. No new timers -//! can be created in the future and there must be no active timers at that -//! time. - -#![macro_escape] - -use std::cell::UnsafeCell; -use std::mem; -use std::rt::bookkeeping; -use std::rt::mutex::StaticNativeMutex; -use std::rt; -use std::task::TaskBuilder; - -use NativeTaskBuilder; - -/// A structure for management of a helper thread. -/// -/// This is generally a static structure which tracks the lifetime of a helper -/// thread. -/// -/// The fields of this helper are all public, but they should not be used, this -/// is for static initialization. -pub struct Helper<M> { - /// Internal lock which protects the remaining fields - pub lock: StaticNativeMutex, - - // You'll notice that the remaining fields are UnsafeCell<T>, and this is - // because all helper thread operations are done through &self, but we need - // these to be mutable (once `lock` is held). - - /// Lazily allocated channel to send messages to the helper thread. - pub chan: UnsafeCell<*mut Sender<M>>, - - /// OS handle used to wake up a blocked helper thread - pub signal: UnsafeCell<uint>, - - /// Flag if this helper thread has booted and been initialized yet. - pub initialized: UnsafeCell<bool>, -} - -macro_rules! helper_init( (static $name:ident: Helper<$m:ty>) => ( - static $name: Helper<$m> = Helper { - lock: ::std::rt::mutex::NATIVE_MUTEX_INIT, - chan: ::std::cell::UnsafeCell { value: 0 as *mut Sender<$m> }, - signal: ::std::cell::UnsafeCell { value: 0 }, - initialized: ::std::cell::UnsafeCell { value: false }, - }; -) ) - -impl<M: Send> Helper<M> { - /// Lazily boots a helper thread, becoming a no-op if the helper has already - /// been spawned. - /// - /// This function will check to see if the thread has been initialized, and - /// if it has it returns quickly. If initialization has not happened yet, - /// the closure `f` will be run (inside of the initialization lock) and - /// passed to the helper thread in a separate task. - /// - /// This function is safe to be called many times. - pub fn boot<T: Send>(&'static self, - f: || -> T, - helper: fn(imp::signal, Receiver<M>, T)) { - unsafe { - let _guard = self.lock.lock(); - if !*self.initialized.get() { - let (tx, rx) = channel(); - *self.chan.get() = mem::transmute(box tx); - let (receive, send) = imp::new(); - *self.signal.get() = send as uint; - - let t = f(); - TaskBuilder::new().native().spawn(proc() { - bookkeeping::decrement(); - helper(receive, rx, t); - self.lock.lock().signal() - }); - - rt::at_exit(proc() { self.shutdown() }); - *self.initialized.get() = true; - } - } - } - - /// Sends a message to a spawned worker thread. - /// - /// This is only valid if the worker thread has previously booted - pub fn send(&'static self, msg: M) { - unsafe { - let _guard = self.lock.lock(); - - // Must send and *then* signal to ensure that the child receives the - // message. Otherwise it could wake up and go to sleep before we - // send the message. - assert!(!self.chan.get().is_null()); - (**self.chan.get()).send(msg); - imp::signal(*self.signal.get() as imp::signal); - } - } - - fn shutdown(&'static self) { - unsafe { - // Shut down, but make sure this is done inside our lock to ensure - // that we'll always receive the exit signal when the thread - // returns. - let guard = self.lock.lock(); - - // Close the channel by destroying it - let chan: Box<Sender<M>> = mem::transmute(*self.chan.get()); - *self.chan.get() = 0 as *mut Sender<M>; - drop(chan); - imp::signal(*self.signal.get() as imp::signal); - - // Wait for the child to exit - guard.wait(); - drop(guard); - - // Clean up after ourselves - self.lock.destroy(); - imp::close(*self.signal.get() as imp::signal); - *self.signal.get() = 0; - } - } -} - -#[cfg(unix)] -mod imp { - use libc; - use std::os; - - use io::file::FileDesc; - - pub type signal = libc::c_int; - - pub fn new() -> (signal, signal) { - let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() }; - (reader, writer) - } - - pub fn signal(fd: libc::c_int) { - FileDesc::new(fd, false).inner_write([0]).ok().unwrap(); - } - - pub fn close(fd: libc::c_int) { - let _fd = FileDesc::new(fd, true); - } -} - -#[cfg(windows)] -mod imp { - use libc::{BOOL, LPCSTR, HANDLE, LPSECURITY_ATTRIBUTES, CloseHandle}; - use std::ptr; - use libc; - - pub type signal = HANDLE; - - pub fn new() -> (HANDLE, HANDLE) { - unsafe { - let handle = CreateEventA(ptr::null_mut(), libc::FALSE, libc::FALSE, - ptr::null()); - (handle, handle) - } - } - - pub fn signal(handle: HANDLE) { - assert!(unsafe { SetEvent(handle) != 0 }); - } - - pub fn close(handle: HANDLE) { - assert!(unsafe { CloseHandle(handle) != 0 }); - } - - extern "system" { - fn CreateEventA(lpSecurityAttributes: LPSECURITY_ATTRIBUTES, - bManualReset: BOOL, - bInitialState: BOOL, - lpName: LPCSTR) -> HANDLE; - fn SetEvent(hEvent: HANDLE) -> BOOL; - } -} diff --git a/src/libnative/io/mod.rs b/src/libnative/io/mod.rs index 2a76bc29f7c..1d0b9f40d07 100644 --- a/src/libnative/io/mod.rs +++ b/src/libnative/io/mod.rs @@ -32,8 +32,6 @@ use std::num; // Local re-exports pub use self::process::Process; -mod helper_thread; - // Native I/O implementations pub mod process; mod util; |
