]> git.lizzy.rs Git - rust.git/blob - src/libstd/rt/local.rs
Fix bug in `match`ing struct patterns
[rust.git] / src / libstd / rt / local.rs
1 // Copyright 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 use option::{Option, Some, None};
12 use rt::sched::Scheduler;
13 use rt::task::Task;
14 use rt::local_ptr;
15 use rt::rtio::{EventLoop, IoFactoryObject};
16 //use borrow::to_uint;
17 use cell::Cell;
18
19 pub trait Local {
20     fn put(value: ~Self);
21     fn take() -> ~Self;
22     fn exists() -> bool;
23     fn borrow<T>(f: &fn(&mut Self) -> T) -> T;
24     unsafe fn unsafe_borrow() -> *mut Self;
25     unsafe fn try_unsafe_borrow() -> Option<*mut Self>;
26 }
27
28 impl Local for Task {
29     fn put(value: ~Task) { unsafe { local_ptr::put(value) } }
30     fn take() -> ~Task { unsafe { local_ptr::take() } }
31     fn exists() -> bool { local_ptr::exists() }
32     fn borrow<T>(f: &fn(&mut Task) -> T) -> T {
33         let mut res: Option<T> = None;
34         let res_ptr: *mut Option<T> = &mut res;
35         unsafe {
36             do local_ptr::borrow |task| {
37                 let result = f(task);
38                 *res_ptr = Some(result);
39             }
40         }
41         match res {
42             Some(r) => { r }
43             None => { rtabort!("function failed in local_borrow") }
44         }
45     }
46     unsafe fn unsafe_borrow() -> *mut Task { local_ptr::unsafe_borrow() }
47     unsafe fn try_unsafe_borrow() -> Option<*mut Task> {
48         if Local::exists::<Task>() {
49             Some(Local::unsafe_borrow())
50         } else {
51             None
52         }
53     }
54 }
55
56 impl Local for Scheduler {
57     fn put(value: ~Scheduler) {
58         let value = Cell::new(value);
59         do Local::borrow::<Task,()> |task| {
60             let task = task;
61             task.sched = Some(value.take());
62         };
63     }
64     fn take() -> ~Scheduler {
65         do Local::borrow::<Task,~Scheduler> |task| {
66             let sched = task.sched.take_unwrap();
67             let task = task;
68             task.sched = None;
69             sched
70         }
71     }
72     fn exists() -> bool {
73         do Local::borrow::<Task,bool> |task| {
74             match task.sched {
75                 Some(ref _task) => true,
76                 None => false
77             }
78         }
79     }
80     fn borrow<T>(f: &fn(&mut Scheduler) -> T) -> T {
81         do Local::borrow::<Task, T> |task| {
82             match task.sched {
83                 Some(~ref mut task) => {
84                     f(task)
85                 }
86                 None => {
87                     rtabort!("no scheduler")
88                 }
89             }
90         }
91     }
92     unsafe fn unsafe_borrow() -> *mut Scheduler {
93         match (*Local::unsafe_borrow::<Task>()).sched {
94             Some(~ref mut sched) => {
95                 let s: *mut Scheduler = &mut *sched;
96                 return s;
97             }
98             None => {
99                 rtabort!("no scheduler")
100             }
101         }
102     }
103     unsafe fn try_unsafe_borrow() -> Option<*mut Scheduler> {
104         if Local::exists::<Scheduler>() {
105             Some(Local::unsafe_borrow())
106         } else {
107             None
108         }
109     }
110 }
111
112 // XXX: This formulation won't work once ~IoFactoryObject is a real trait pointer
113 impl Local for IoFactoryObject {
114     fn put(_value: ~IoFactoryObject) { rtabort!("unimpl") }
115     fn take() -> ~IoFactoryObject { rtabort!("unimpl") }
116     fn exists() -> bool { rtabort!("unimpl") }
117     fn borrow<T>(_f: &fn(&mut IoFactoryObject) -> T) -> T { rtabort!("unimpl") }
118     unsafe fn unsafe_borrow() -> *mut IoFactoryObject {
119         let sched = Local::unsafe_borrow::<Scheduler>();
120         let io: *mut IoFactoryObject = (*sched).event_loop.io().unwrap();
121         return io;
122     }
123     unsafe fn try_unsafe_borrow() -> Option<*mut IoFactoryObject> { rtabort!("unimpl") }
124 }
125
126
127 #[cfg(test)]
128 mod test {
129     use unstable::run_in_bare_thread;
130     use rt::test::*;
131     use super::*;
132     use rt::task::Task;
133     use rt::local_ptr;
134
135     #[test]
136     fn thread_local_task_smoke_test() {
137         do run_in_bare_thread {
138             local_ptr::init_tls_key();
139             let mut sched = ~new_test_uv_sched();
140             let task = ~Task::new_root(&mut sched.stack_pool, || {});
141             Local::put(task);
142             let task: ~Task = Local::take();
143             cleanup_task(task);
144         }
145     }
146
147     #[test]
148     fn thread_local_task_two_instances() {
149         do run_in_bare_thread {
150             local_ptr::init_tls_key();
151             let mut sched = ~new_test_uv_sched();
152             let task = ~Task::new_root(&mut sched.stack_pool, || {});
153             Local::put(task);
154             let task: ~Task = Local::take();
155             cleanup_task(task);
156             let task = ~Task::new_root(&mut sched.stack_pool, || {});
157             Local::put(task);
158             let task: ~Task = Local::take();
159             cleanup_task(task);
160         }
161
162     }
163
164     #[test]
165     fn borrow_smoke_test() {
166         do run_in_bare_thread {
167             local_ptr::init_tls_key();
168             let mut sched = ~new_test_uv_sched();
169             let task = ~Task::new_root(&mut sched.stack_pool, || {});
170             Local::put(task);
171
172             unsafe {
173                 let _task: *mut Task = Local::unsafe_borrow();
174             }
175             let task: ~Task = Local::take();
176             cleanup_task(task);
177         }
178     }
179
180     #[test]
181     fn borrow_with_return() {
182         do run_in_bare_thread {
183             local_ptr::init_tls_key();
184             let mut sched = ~new_test_uv_sched();
185             let task = ~Task::new_root(&mut sched.stack_pool, || {});
186             Local::put(task);
187
188             let res = do Local::borrow::<Task,bool> |_task| {
189                 true
190             };
191             assert!(res)
192                 let task: ~Task = Local::take();
193             cleanup_task(task);
194         }
195     }
196
197 }
198