70ed3a48df
This is an implementation of [RFC 578][rfc] which adds a new `std::env` module to replace most of the functionality in the current `std::os` module. More details can be found in the RFC itself, but as a summary the following methods have all been deprecated: [rfc]: https://github.com/rust-lang/rfcs/pull/578 * `os::args_as_bytes` => `env::args` * `os::args` => `env::args` * `os::consts` => `env::consts` * `os::dll_filename` => no replacement, use `env::consts` directly * `os::page_size` => `env::page_size` * `os::make_absolute` => use `env::current_dir` + `join` instead * `os::getcwd` => `env::current_dir` * `os::change_dir` => `env::set_current_dir` * `os::homedir` => `env::home_dir` * `os::tmpdir` => `env::temp_dir` * `os::join_paths` => `env::join_paths` * `os::split_paths` => `env::split_paths` * `os::self_exe_name` => `env::current_exe` * `os::self_exe_path` => use `env::current_exe` + `pop` * `os::set_exit_status` => `env::set_exit_status` * `os::get_exit_status` => `env::get_exit_status` * `os::env` => `env::vars` * `os::env_as_bytes` => `env::vars` * `os::getenv` => `env::var` or `env::var_string` * `os::getenv_as_bytes` => `env::var` * `os::setenv` => `env::set_var` * `os::unsetenv` => `env::remove_var` Many function signatures have also been tweaked for various purposes, but the main changes were: * `Vec`-returning APIs now all return iterators instead * All APIs are now centered around `OsString` instead of `Vec<u8>` or `String`. There is currently on convenience API, `env::var_string`, which can be used to get the value of an environment variable as a unicode `String`. All old APIs are `#[deprecated]` in-place and will remain for some time to allow for migrations. The semantics of the APIs have been tweaked slightly with regard to dealing with invalid unicode (panic instead of replacement). The new `std::env` module is all contained within the `env` feature, so crates must add the following to access the new APIs: #![feature(env)] [breaking-change]
102 lines
3.5 KiB
Rust
102 lines
3.5 KiB
Rust
// Copyright 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.
|
|
|
|
use boxed::Box;
|
|
use cmp;
|
|
use mem;
|
|
use ptr;
|
|
use libc;
|
|
use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES, SIZE_T, BOOL,
|
|
LPVOID, DWORD, LPDWORD, HANDLE};
|
|
use thunk::Thunk;
|
|
use sys_common::stack::RED_ZONE;
|
|
use sys_common::thread::*;
|
|
|
|
pub type rust_thread = HANDLE;
|
|
pub type rust_thread_return = DWORD;
|
|
|
|
pub type StartFn = extern "system" fn(*mut libc::c_void) -> rust_thread_return;
|
|
|
|
#[no_stack_check]
|
|
pub extern "system" fn thread_start(main: *mut libc::c_void) -> rust_thread_return {
|
|
return start_thread(main);
|
|
}
|
|
|
|
pub mod guard {
|
|
pub unsafe fn main() -> uint {
|
|
0
|
|
}
|
|
|
|
pub unsafe fn current() -> uint {
|
|
0
|
|
}
|
|
|
|
pub unsafe fn init() {
|
|
}
|
|
}
|
|
|
|
pub unsafe fn create(stack: uint, p: Thunk) -> rust_thread {
|
|
let arg: *mut libc::c_void = mem::transmute(box p);
|
|
// FIXME On UNIX, we guard against stack sizes that are too small but
|
|
// that's because pthreads enforces that stacks are at least
|
|
// PTHREAD_STACK_MIN bytes big. Windows has no such lower limit, it's
|
|
// just that below a certain threshold you can't do anything useful.
|
|
// That threshold is application and architecture-specific, however.
|
|
// For now, the only requirement is that it's big enough to hold the
|
|
// red zone. Round up to the next 64 kB because that's what the NT
|
|
// kernel does, might as well make it explicit. With the current
|
|
// 20 kB red zone, that makes for a 64 kB minimum stack.
|
|
let stack_size = (cmp::max(stack, RED_ZONE) + 0xfffe) & (-0xfffe - 1);
|
|
let ret = CreateThread(ptr::null_mut(), stack_size as libc::size_t,
|
|
thread_start, arg, 0, ptr::null_mut());
|
|
|
|
if ret as uint == 0 {
|
|
// be sure to not leak the closure
|
|
let _p: Box<Thunk> = mem::transmute(arg);
|
|
panic!("failed to spawn native thread: {:?}", ret);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
pub unsafe fn set_name(_name: &str) {
|
|
// Windows threads are nameless
|
|
// The names in MSVC debugger are obtained using a "magic" exception,
|
|
// which requires a use of MS C++ extensions.
|
|
// See https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
|
|
}
|
|
|
|
pub unsafe fn join(native: rust_thread) {
|
|
use libc::consts::os::extra::INFINITE;
|
|
WaitForSingleObject(native, INFINITE);
|
|
}
|
|
|
|
pub unsafe fn detach(native: rust_thread) {
|
|
assert!(libc::CloseHandle(native) != 0);
|
|
}
|
|
|
|
pub unsafe fn yield_now() {
|
|
// This function will return 0 if there are no other threads to execute,
|
|
// but this also means that the yield was useless so this isn't really a
|
|
// case that needs to be worried about.
|
|
SwitchToThread();
|
|
}
|
|
|
|
#[allow(non_snake_case)]
|
|
extern "system" {
|
|
fn CreateThread(lpThreadAttributes: LPSECURITY_ATTRIBUTES,
|
|
dwStackSize: SIZE_T,
|
|
lpStartAddress: StartFn,
|
|
lpParameter: LPVOID,
|
|
dwCreationFlags: DWORD,
|
|
lpThreadId: LPDWORD) -> HANDLE;
|
|
fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
|
|
fn SwitchToThread() -> BOOL;
|
|
}
|