Fallout from libgreen and libnative removal

This commit is contained in:
Aaron Turon 2014-11-14 14:38:41 -08:00
parent a68ec98166
commit 40c78ab037
28 changed files with 47 additions and 349 deletions

View File

@ -37,7 +37,7 @@
#
# DEPS_<crate>
# These lists are the dependencies of the <crate> that is to be built.
# Rust dependencies are listed bare (i.e. std, green) and native
# Rust dependencies are listed bare (i.e. std) and native
# dependencies have a "native:" prefix (i.e. native:hoedown). All deps
# will be built before the crate itself is built.
#
@ -49,7 +49,7 @@
# automatically generated for all stage/host/target combinations.
################################################################################
TARGET_CRATES := libc std green flate arena term \
TARGET_CRATES := libc std flate arena term \
serialize sync getopts collections test time rand \
log regex graphviz core rbml alloc rustrt \
unicode
@ -66,7 +66,6 @@ DEPS_rustrt := alloc core libc collections native:rustrt_native
DEPS_std := core libc rand alloc collections rustrt sync unicode \
native:rust_builtin native:backtrace
DEPS_graphviz := std
DEPS_green := std native:context_switch
DEPS_syntax := std term serialize log fmt_macros arena libc
DEPS_rustc_trans := rustc rustc_back rustc_llvm libc
DEPS_rustc := syntax flate arena serialize getopts rbml \

View File

@ -9,8 +9,6 @@ Source layout:
| `libcore/` | The Rust core library |
| `libdebug/` | Debugging utilities |
| `libstd/` | The standard library (imported and linked by default) |
| `libgreen/` | The M:N runtime library |
| `libnative/` | The 1:1 runtime library |
| `libsyntax/` | The Rust parser and pretty-printer |
| `libtest/` | Rust's test-runner code |
| ------------------- | --------------------------------------------------------- |

View File

@ -999,14 +999,14 @@ An example of what will and will not work for `use` items:
```
# #![allow(unused_imports)]
use foo::native::start; // good: foo is at the root of the crate
use foo::core::iter; // good: foo is at the root of the crate
use foo::baz::foobaz; // good: foo is at the root of the crate
mod foo {
extern crate native;
extern crate core;
use foo::native::start; // good: foo is at crate root
// use native::start; // bad: native is not at the crate root
use foo::core::iter; // good: foo is at crate root
// use core::iter; // bad: native is not at the crate root
use self::baz::foobaz; // good: self refers to module 'foo'
use foo::bar::foobar; // good: foo is at crate root

View File

@ -73,7 +73,6 @@ extern crate libc;
// Allow testing this library
#[cfg(test)] extern crate native;
#[cfg(test)] #[phase(plugin, link)] extern crate std;
#[cfg(test)] #[phase(plugin, link)] extern crate log;

View File

@ -31,7 +31,6 @@
extern crate unicode;
extern crate alloc;
#[cfg(test)] extern crate native;
#[cfg(test)] extern crate test;
#[cfg(test)] #[phase(plugin, link)] extern crate std;

View File

@ -83,7 +83,6 @@ extern crate core;
#[cfg(test)] extern crate std;
#[cfg(test)] extern crate test;
#[cfg(test)] extern crate native;
pub use self::Nullable::*;

View File

@ -33,7 +33,6 @@ extern crate core;
#[cfg(test)] #[phase(plugin, link)] extern crate std;
#[cfg(test)] #[phase(plugin, link)] extern crate log;
#[cfg(test)] extern crate native;
use core::prelude::*;

View File

@ -30,7 +30,6 @@ extern crate collections;
#[cfg(test)] extern crate "rustrt" as realrustrt;
#[cfg(test)] extern crate test;
#[cfg(test)] extern crate native;
#[cfg(test)] #[phase(plugin, link)] extern crate std;

View File

@ -65,14 +65,7 @@ pub unsafe fn report() {
#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
unsafe fn get_task_guard_page() -> Option<uint> {
let task: Option<*mut Task> = Local::try_unsafe_borrow();
task.map(|task| {
let runtime = (*task).take_runtime();
let guard = runtime.stack_guard();
(*task).put_runtime(runtime);
guard.unwrap_or(0)
})
task.map(|task| (&*task).stack_guard().unwrap_or(0))
}
#[cfg(windows)]

View File

@ -740,8 +740,6 @@ impl Drop for Process {
mod tests {
#![allow(unused_imports)]
extern crate native;
use super::*;
use prelude::*;
use io::timer::*;

View File

@ -117,7 +117,6 @@
#![reexport_test_harness_main = "test_main"]
#[cfg(test)] extern crate green;
#[cfg(test)] #[phase(plugin, link)] extern crate log;
extern crate alloc;

View File

@ -58,7 +58,7 @@ Several modules in `core` are clients of `rt`:
use failure;
use rustrt;
use startup;
use os;
// Reexport some of our utilities which are expected by other crates.
pub use self::util::{default_sched_threads, min_stack, running_on_valgrind};
@ -66,9 +66,9 @@ pub use self::util::{default_sched_threads, min_stack, running_on_valgrind};
// Reexport functionality from librustrt and other crates underneath the
// standard library which work together to create the entire runtime.
pub use alloc::heap;
pub use rustrt::{task, local, mutex, exclusive, stack, args, rtio, thread};
pub use rustrt::{task, local, mutex, exclusive, stack, args, thread};
pub use rustrt::{Stdio, Stdout, Stderr, begin_unwind, begin_unwind_fmt};
pub use rustrt::{bookkeeping, at_exit, unwind, DEFAULT_ERROR_CODE, Runtime};
pub use rustrt::{at_exit, unwind, DEFAULT_ERROR_CODE};
// Simple backtrace functionality (to print on panic)
pub mod backtrace;
@ -95,7 +95,7 @@ static OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20);
#[cfg(not(test))]
#[lang = "start"]
fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
use std::mem;
use mem;
start(argc, argv, proc() {
let main: extern "Rust" fn() = unsafe { mem::transmute(main) };
main();
@ -147,8 +147,8 @@ pub fn start(argc: int, argv: *const *const u8, main: proc()) -> int {
init(argc, argv);
let mut exit_code = None;
let mut main = Some(main);
let mut task = task::new((my_stack_bottom, my_stack_top),
rt::thread::main_guard_page());
let mut task = Task::new(Some((my_stack_bottom, my_stack_top)),
Some(rt::thread::main_guard_page()));
task.name = Some(str::Slice("<main>"));
drop(task.run(|| {
unsafe {

View File

@ -21,7 +21,7 @@
//! time.
use mem;
use rt::bookkeeping;
use rustrt::bookkeeping;
use rt::mutex::StaticNativeMutex;
use rt;
use cell::UnsafeCell;

View File

@ -11,11 +11,7 @@
//! Task creation
//!
//! An executing Rust program consists of a collection of tasks, each
//! with their own stack and local state. A Rust task is typically
//! backed by an operating system thread, making tasks 'just threads',
//! but may also be implemented via other strategies as well
//! (e.g. Rust comes with the [`green`](../../green/index.html)
//! scheduling crate for creating tasks backed by green threads).
//! with their own stack and local state.
//!
//! Tasks generally have their memory *isolated* from each other by
//! virtue of Rust's owned types (which of course may only be owned by
@ -36,13 +32,6 @@
//! the main task panics the application will exit with a non-zero
//! exit code.
//!
//! # Basic task scheduling
//!
//! By default, every task is created with the same "flavor" as the calling task.
//! This flavor refers to the scheduling mode, with two possibilities currently
//! being 1:1 and M:N modes. Green (M:N) tasks are cooperatively scheduled and
//! native (1:1) tasks are scheduled by the OS kernel.
//!
//! ## Example
//!
//! ```rust
@ -50,46 +39,6 @@
//! println!("Hello, World!");
//! })
//! ```
//!
//! # Advanced task scheduling
//!
//! Task spawning can also be configured to use a particular scheduler, to
//! redirect the new task's output, or to yield a `future` representing the
//! task's final result. The configuration is established using the
//! `TaskBuilder` API:
//!
//! ## Example
//!
//! ```rust
//! extern crate green;
//! extern crate native;
//!
//! use std::task::TaskBuilder;
//! use green::{SchedPool, PoolConfig, GreenTaskBuilder};
//! use native::NativeTaskBuilder;
//!
//! # fn main() {
//! // Create a green scheduler pool with the default configuration
//! let mut pool = SchedPool::new(PoolConfig::new());
//!
//! // Spawn a task in the green pool
//! let mut fut_green = TaskBuilder::new().green(&mut pool).try_future(proc() {
//! /* ... */
//! });
//!
//! // Spawn a native task
//! let mut fut_native = TaskBuilder::new().native().try_future(proc() {
//! /* ... */
//! });
//!
//! // Wait for both tasks to finish, recording their outcome
//! let res_green = fut_green.unwrap();
//! let res_native = fut_native.unwrap();
//!
//! // Shut down the green scheduler pool
//! pool.shutdown();
//! # }
//! ```
#![unstable = "The task spawning model will be changed as part of runtime reform, and the module \
will likely be renamed from `task` to `thread`."]
@ -108,26 +57,6 @@ use str::{Str, SendStr, IntoMaybeOwned};
use string::{String, ToString};
use sync::Future;
/// A means of spawning a task
pub trait Spawner {
/// Spawn a task, given low-level task options.
fn spawn(self, opts: task::TaskOpts, f: proc():Send);
}
/// The default task spawner, which spawns siblings to the current task.
pub struct SiblingSpawner;
impl Spawner for SiblingSpawner {
fn spawn(self, opts: task::TaskOpts, f: proc():Send) {
// bind tb to provide type annotation
let tb: Option<Box<Task>> = Local::try_take();
match tb {
Some(t) => t.spawn_sibling(opts, f),
None => panic!("need a local task to spawn a sibling task"),
};
}
}
/// The task builder type.
///
/// Provides detailed control over the properties and behavior of new tasks.
@ -139,7 +68,7 @@ impl Spawner for SiblingSpawner {
// when you try to reuse the builder to spawn a new task. We'll just
// sidestep that whole issue by making builders uncopyable and making
// the run function move them in.
pub struct TaskBuilder<S = SiblingSpawner> {
pub struct TaskBuilder {
// A name for the task-to-be, for identification in panic messages
name: Option<SendStr>,
// The size of the stack for the spawned task
@ -148,88 +77,60 @@ pub struct TaskBuilder<S = SiblingSpawner> {
stdout: Option<Box<Writer + Send>>,
// Task-local stderr
stderr: Option<Box<Writer + Send>>,
// The mechanics of actually spawning the task (i.e.: green or native)
spawner: S,
// Optionally wrap the eventual task body
gen_body: Option<proc(v: proc():Send):Send -> proc():Send>,
nocopy: marker::NoCopy,
}
impl TaskBuilder<SiblingSpawner> {
impl TaskBuilder {
/// Generate the base configuration for spawning a task, off of which more
/// configuration methods can be chained.
pub fn new() -> TaskBuilder<SiblingSpawner> {
pub fn new() -> TaskBuilder {
TaskBuilder {
name: None,
stack_size: None,
stdout: None,
stderr: None,
spawner: SiblingSpawner,
gen_body: None,
nocopy: marker::NoCopy,
}
}
}
impl<S: Spawner> TaskBuilder<S> {
impl TaskBuilder {
/// Name the task-to-be. Currently the name is used for identification
/// only in panic messages.
#[unstable = "IntoMaybeOwned will probably change."]
pub fn named<T: IntoMaybeOwned<'static>>(mut self, name: T) -> TaskBuilder<S> {
pub fn named<T: IntoMaybeOwned<'static>>(mut self, name: T) -> TaskBuilder {
self.name = Some(name.into_maybe_owned());
self
}
/// Set the size of the stack for the new task.
pub fn stack_size(mut self, size: uint) -> TaskBuilder<S> {
pub fn stack_size(mut self, size: uint) -> TaskBuilder {
self.stack_size = Some(size);
self
}
/// Redirect task-local stdout.
#[experimental = "May not want to make stdio overridable here."]
pub fn stdout(mut self, stdout: Box<Writer + Send>) -> TaskBuilder<S> {
pub fn stdout(mut self, stdout: Box<Writer + Send>) -> TaskBuilder {
self.stdout = Some(stdout);
self
}
/// Redirect task-local stderr.
#[experimental = "May not want to make stdio overridable here."]
pub fn stderr(mut self, stderr: Box<Writer + Send>) -> TaskBuilder<S> {
pub fn stderr(mut self, stderr: Box<Writer + Send>) -> TaskBuilder {
self.stderr = Some(stderr);
self
}
/// Set the spawning mechanism for the task.
///
/// The `TaskBuilder` API configures a task to be spawned, but defers to the
/// "spawner" to actually create and spawn the task. The `spawner` method
/// should not be called directly by `TaskBuiler` clients. It is intended
/// for use by downstream crates (like `native` and `green`) that implement
/// tasks. These downstream crates then add extension methods to the
/// builder, like `.native()` and `.green(pool)`, that actually set the
/// spawner.
pub fn spawner<T: Spawner>(self, spawner: T) -> TaskBuilder<T> {
// repackage the entire TaskBuilder since its type is changing.
let TaskBuilder {
name, stack_size, stdout, stderr, spawner: _, gen_body, nocopy
} = self;
TaskBuilder {
name: name,
stack_size: stack_size,
stdout: stdout,
stderr: stderr,
spawner: spawner,
gen_body: gen_body,
nocopy: nocopy,
}
}
// Where spawning actually happens (whether yielding a future or not)
fn spawn_internal(self, f: proc():Send,
on_exit: Option<proc(Result<(), Box<Any + Send>>):Send>) {
let TaskBuilder {
name, stack_size, stdout, stderr, spawner, mut gen_body, nocopy: _
name, stack_size, stdout, stderr, mut gen_body, nocopy: _
} = self;
let f = match gen_body.take() {
Some(gen) => gen(f),
@ -348,11 +249,8 @@ pub fn name() -> Option<String> {
/// Yield control to the task scheduler.
#[unstable = "Name will change."]
pub fn deschedule() {
use rt::local::Local;
// FIXME(#7544): Optimize this, since we know we won't block.
let task: Box<Task> = Local::take();
task.yield_now();
use rt::task::Task;
Task::yield_now();
}
/// True if the running task is currently panicking (e.g. will return `true` inside a

View File

@ -42,7 +42,6 @@
//! ```
//! use std::sync::Arc;
//! use std::sync::atomic::{AtomicUint, SeqCst};
//! use std::task::deschedule;
//!
//! fn main() {
//! let spinlock = Arc::new(AtomicUint::new(1));
@ -53,13 +52,7 @@
//! });
//!
//! // Wait for the other task to release the lock
//! while spinlock.load(SeqCst) != 0 {
//! // Since tasks may not be preemptive (if they are green threads)
//! // yield to the scheduler to let the other task run. Low level
//! // concurrent code needs to take into account Rust's two threading
//! // models.
//! deschedule();
//! }
//! while spinlock.load(SeqCst) != 0 {}
//! }
//! ```
//!

View File

@ -65,10 +65,6 @@
//! the `try_send` method on a `SyncSender`, but no other operations are
//! guaranteed to be safe.
//!
//! Additionally, channels can interoperate between runtimes. If one task in a
//! program is running on libnative and another is running on libgreen, they can
//! still communicate with one another using channels.
//!
//! # Example
//!
//! Simple usage:
@ -328,13 +324,10 @@ pub use self::TrySendError::*;
use self::Flavor::*;
use alloc::arc::Arc;
use alloc::boxed::Box;
use core::cell::Cell;
use core::kinds::marker;
use core::mem;
use core::cell::UnsafeCell;
use rustrt::local::Local;
use rustrt::task::{Task, BlockedTask};
use rustrt::task::BlockedTask;
pub use comm::select::{Select, Handle};
@ -345,21 +338,12 @@ macro_rules! test (
use std::prelude::*;
use native;
use comm::*;
use super::*;
use super::super::*;
use std::task;
fn f() $b
$(#[$a])* #[test] fn uv() { f() }
$(#[$a])* #[test] fn native() {
use native;
let (tx, rx) = channel();
spawn(proc() { tx.send(f()) });
rx.recv();
}
$(#[$a])* #[test] fn f() { $b }
}
)
)
@ -370,16 +354,11 @@ mod shared;
mod stream;
mod sync;
// Use a power of 2 to allow LLVM to optimize to something that's not a
// division, this is hit pretty regularly.
static RESCHED_FREQ: int = 256;
/// The receiving-half of Rust's channel type. This half can only be owned by
/// one task
#[unstable]
pub struct Receiver<T> {
inner: UnsafeCell<Flavor<T>>,
receives: Cell<uint>,
// can't share in an arc
_marker: marker::NoSync,
}
@ -397,7 +376,6 @@ pub struct Messages<'a, T:'a> {
#[unstable]
pub struct Sender<T> {
inner: UnsafeCell<Flavor<T>>,
sends: Cell<uint>,
// can't share in an arc
_marker: marker::NoSync,
}
@ -544,7 +522,6 @@ impl<T: Send> Sender<T> {
fn new(inner: Flavor<T>) -> Sender<T> {
Sender {
inner: UnsafeCell::new(inner),
sends: Cell::new(0),
_marker: marker::NoSync,
}
}
@ -608,21 +585,6 @@ impl<T: Send> Sender<T> {
/// ```
#[unstable = "this function may be renamed to send() in the future"]
pub fn send_opt(&self, t: T) -> Result<(), T> {
// In order to prevent starvation of other tasks in situations where
// a task sends repeatedly without ever receiving, we occasionally
// yield instead of doing a send immediately.
//
// Don't unconditionally attempt to yield because the TLS overhead can
// be a bit much, and also use `try_take` instead of `take` because
// there's no reason that this send shouldn't be usable off the
// runtime.
let cnt = self.sends.get() + 1;
self.sends.set(cnt);
if cnt % (RESCHED_FREQ as uint) == 0 {
let task: Option<Box<Task>> = Local::try_take();
task.map(|t| t.maybe_yield());
}
let (new_inner, ret) = match *unsafe { self.inner() } {
Oneshot(ref p) => {
unsafe {
@ -809,7 +771,7 @@ impl<T: Send> Drop for SyncSender<T> {
impl<T: Send> Receiver<T> {
fn new(inner: Flavor<T>) -> Receiver<T> {
Receiver { inner: UnsafeCell::new(inner), receives: Cell::new(0), _marker: marker::NoSync }
Receiver { inner: UnsafeCell::new(inner), _marker: marker::NoSync }
}
/// Blocks waiting for a value on this receiver
@ -854,17 +816,6 @@ impl<T: Send> Receiver<T> {
/// This function cannot panic.
#[unstable = "the return type of this function may be altered"]
pub fn try_recv(&self) -> Result<T, TryRecvError> {
// If a thread is spinning in try_recv, we should take the opportunity
// to reschedule things occasionally. See notes above in scheduling on
// sends for why this doesn't always hit TLS, and also for why this uses
// `try_take` instead of `take`.
let cnt = self.receives.get() + 1;
self.receives.set(cnt);
if cnt % (RESCHED_FREQ as uint) == 0 {
let task: Option<Box<Task>> = Local::try_take();
task.map(|t| t.maybe_yield());
}
loop {
let new_port = match *unsafe { self.inner() } {
Oneshot(ref p) => {

View File

@ -279,17 +279,6 @@ impl<T: Send> Packet<T> {
// because the remote sender should finish their enqueue
// operation "very quickly".
//
// Note that this yield loop does *not* attempt to do a green
// yield (regardless of the context), but *always* performs an
// OS-thread yield. The reasoning for this is that the pusher in
// question which is causing the inconsistent state is
// guaranteed to *not* be a blocked task (green tasks can't get
// pre-empted), so it must be on a different OS thread. Also,
// `try_recv` is normally a "guaranteed no rescheduling" context
// in a green-thread situation. By yielding control of the
// thread, we will hopefully allow time for the remote task on
// the other OS thread to make progress.
//
// Avoiding this yield loop would require a different queue
// abstraction which provides the guarantee that after M
// pushes have succeeded, at least M pops will succeed. The

View File

@ -38,7 +38,6 @@ extern crate collections;
extern crate rustrt;
#[cfg(test)] extern crate test;
#[cfg(test)] extern crate native;
#[cfg(test)] #[phase(plugin, link)] extern crate std;
pub use alloc::arc::{Arc, Weak};

View File

@ -1,41 +0,0 @@
// Copyright 2013 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.
#![no_start]
extern crate green;
use std::task::spawn;
use std::os;
use std::uint;
// Very simple spawn rate test. Spawn N tasks that do nothing and
// return.
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
green::start(argc, argv, green::basic::event_loop, main)
}
fn main() {
let args = os::args();
let args = args.as_slice();
let n = if args.len() == 2 {
from_str::<uint>(args[1].as_slice()).unwrap()
} else {
100000
};
for _ in range(0, n) {
spawn(proc() {});
}
}

View File

@ -1,25 +0,0 @@
// Copyright 2012 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.
// This is (hopefully) a quick test to get a good idea about spawning
// performance in libgreen.
extern crate green;
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
green::start(argc, argv, green::basic::event_loop, main)
}
fn main() {
for _ in range(1u32, 100_000) {
spawn(proc() {})
}
}

View File

@ -3,7 +3,6 @@
#![feature(globs)]
#[phase(plugin, link)]
extern crate "std" as std;
extern crate "native" as rt;
#[prelude_import]
use std::prelude::*;
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT

View File

@ -1,21 +0,0 @@
// 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.
// ignore-android (FIXME #11419)
// error-pattern:explicit panic
extern crate native;
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
native::start(argc, argv, proc() {
panic!();
})
}

View File

@ -11,11 +11,11 @@
#![crate_name="boot"]
#![crate_type="dylib"]
extern crate native;
use std::rt;
#[no_mangle] // this needs to get called from C
pub extern "C" fn foo(argc: int, argv: *const *const u8) -> int {
native::start(argc, argv, proc() {
rt::start(argc, argv, proc() {
spawn(proc() {
println!("hello");
});

View File

@ -10,18 +10,11 @@
// no-pretty-expanded FIXME #15189
// ignore-windows FIXME #13259
extern crate native;
use std::os;
use std::io::process::Command;
use std::finally::Finally;
use std::str;
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
native::start(argc, argv, main)
}
#[inline(never)]
fn foo() {
let _v = vec![1i, 2, 3];

View File

@ -15,7 +15,6 @@
#[phase(plugin, link)]
extern crate log;
extern crate native;
use log::{set_logger, Logger, LogRecord};
use std::fmt;
@ -30,13 +29,6 @@ impl Logger for MyWriter {
}
}
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
native::start(argc, argv, proc() {
main();
})
}
fn main() {
let (tx, rx) = channel();
let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));

View File

@ -8,17 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
extern crate native;
use std::io::timer;
use std::time::Duration;
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
native::start(argc, argv, main)
}
fn main() {
timer::sleep(Duration::milliseconds(250));
}

View File

@ -8,24 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
extern crate green;
static mut DROP: int = 0i;
static mut DROP_S: int = 0i;
static mut DROP_T: int = 0i;
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
let ret = green::start(argc, argv, green::basic::event_loop, main);
unsafe {
assert_eq!(2, DROP);
assert_eq!(1, DROP_S);
assert_eq!(1, DROP_T);
}
ret
}
struct S;
impl Drop for S {
fn drop(&mut self) {
@ -48,7 +34,7 @@ impl Drop for T {
}
fn g(ref _t: T) {}
fn main() {
fn do_test() {
let s = S;
f(s);
unsafe {
@ -59,3 +45,12 @@ fn main() {
g(t);
unsafe { assert_eq!(1, DROP_T); }
}
fn main() {
do_test();
unsafe {
assert_eq!(2, DROP);
assert_eq!(1, DROP_S);
assert_eq!(1, DROP_T);
}
}

View File

@ -8,12 +8,14 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
extern crate native;
extern crate rustrt;
use std::io::process::{Command, ProcessOutput};
use std::os;
use std::str;
use std::rt::unwind::try;
use std::rt;
use rustrt::unwind::try;
local_data_key!(foo: int)
@ -36,7 +38,7 @@ fn start(argc: int, argv: *const *const u8) -> int {
return 0
}
native::start(argc, argv, main)
rt::start(argc, argv, main)
}
fn main() {