]> git.lizzy.rs Git - rust.git/blob - src/libstd/unstable/mod.rs
Add externfn macro and correctly label fixed_stack_segments
[rust.git] / src / libstd / unstable / mod.rs
1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #[doc(hidden)];
12
13 use comm::{GenericChan, GenericPort};
14 use comm;
15 use prelude::*;
16 use task;
17
18 pub mod dynamic_lib;
19
20 pub mod finally;
21 pub mod intrinsics;
22 pub mod simd;
23 pub mod extfmt;
24 #[cfg(not(test))]
25 pub mod lang;
26 pub mod sync;
27 pub mod atomics;
28 pub mod raw;
29
30 /**
31
32 Start a new thread outside of the current runtime context and wait
33 for it to terminate.
34
35 The executing thread has no access to a task pointer and will be using
36 a normal large stack.
37 */
38 pub fn run_in_bare_thread(f: ~fn()) {
39     use cell::Cell;
40     use rt::thread::Thread;
41
42     let f_cell = Cell::new(f);
43     let (port, chan) = comm::stream();
44     // FIXME #4525: Unfortunate that this creates an extra scheduler but it's
45     // necessary since rust_raw_thread_join is blocking
46     do task::spawn_sched(task::SingleThreaded) {
47         Thread::start(f_cell.take()).join();
48         chan.send(());
49     }
50     port.recv();
51 }
52
53 #[test]
54 fn test_run_in_bare_thread() {
55     let i = 100;
56     do run_in_bare_thread {
57         assert_eq!(i, 100);
58     }
59 }
60
61 #[test]
62 fn test_run_in_bare_thread_exchange() {
63     // Does the exchange heap work without the runtime?
64     let i = ~100;
65     do run_in_bare_thread {
66         assert!(i == ~100);
67     }
68 }
69
70
71 /// Changes the current working directory to the specified
72 /// path while acquiring a global lock, then calls `action`.
73 /// If the change is successful, releases the lock and restores the
74 /// CWD to what it was before, returning true.
75 /// Returns false if the directory doesn't exist or if the directory change
76 /// is otherwise unsuccessful.
77 ///
78 /// This is used by test cases to avoid cwd races.
79 ///
80 /// # Safety Note
81 ///
82 /// This uses a pthread mutex so descheduling in the action callback
83 /// can lead to deadlock. Calling change_dir_locked recursively will
84 /// also deadlock.
85 pub fn change_dir_locked(p: &Path, action: &fn()) -> bool {
86     #[fixed_stack_segment]; #[inline(never)];
87
88     use os;
89     use os::change_dir;
90     use unstable::sync::atomically;
91     use unstable::finally::Finally;
92
93     unsafe {
94         // This is really sketchy. Using a pthread mutex so descheduling
95         // in the `action` callback can cause deadlock. Doing it in
96         // `task::atomically` to try to avoid that, but ... I don't know
97         // this is all bogus.
98         return do atomically {
99             rust_take_change_dir_lock();
100
101             do (||{
102                 let old_dir = os::getcwd();
103                 if change_dir(p) {
104                     action();
105                     change_dir(&old_dir)
106                 }
107                 else {
108                     false
109                 }
110             }).finally {
111                 rust_drop_change_dir_lock();
112             }
113         }
114     }
115
116     extern {
117         fn rust_take_change_dir_lock();
118         fn rust_drop_change_dir_lock();
119     }
120 }