]> git.lizzy.rs Git - rust.git/blob - src/test/run-pass/issue-2718.rs
Account for --remap-path-prefix in save-analysis
[rust.git] / src / test / run-pass / issue-2718.rs
1 // Copyright 2012-2014 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
12 #![feature(std_misc)]
13
14 pub type Task = isize;
15
16 // tjc: I don't know why
17 pub mod pipes {
18     use self::state::{empty, full, blocked, terminated};
19     use super::Task;
20     use std::mem::{forget, transmute};
21     use std::mem::{replace, swap};
22     use std::mem;
23     use std::thread;
24     use std::marker::Send;
25
26     pub struct Stuff<T> {
27         state: state,
28         blocked_task: Option<Task>,
29         payload: Option<T>
30     }
31
32     #[derive(PartialEq, Debug)]
33     #[repr(isize)]
34     pub enum state {
35         empty,
36         full,
37         blocked,
38         terminated
39     }
40
41     pub struct packet<T> {
42         state: state,
43         blocked_task: Option<Task>,
44         payload: Option<T>
45     }
46
47     unsafe impl<T:Send> Send for packet<T> {}
48
49     pub fn packet<T:Send>() -> *const packet<T> {
50         unsafe {
51             let p: *const packet<T> = mem::transmute(Box::new(Stuff{
52                 state: empty,
53                 blocked_task: None::<Task>,
54                 payload: None::<T>
55             }));
56             p
57         }
58     }
59
60     mod rusti {
61       pub fn atomic_xchg(_dst: &mut isize, _src: isize) -> isize { panic!(); }
62       pub fn atomic_xchg_acq(_dst: &mut isize, _src: isize) -> isize { panic!(); }
63       pub fn atomic_xchg_rel(_dst: &mut isize, _src: isize) -> isize { panic!(); }
64     }
65
66     // We should consider moving this to ::std::unsafe, although I
67     // suspect graydon would want us to use void pointers instead.
68     pub unsafe fn uniquify<T>(x: *const T) -> Box<T> {
69         mem::transmute(x)
70     }
71
72     pub fn swap_state_acq(dst: &mut state, src: state) -> state {
73         unsafe {
74             transmute(rusti::atomic_xchg_acq(transmute(dst), src as isize))
75         }
76     }
77
78     pub fn swap_state_rel(dst: &mut state, src: state) -> state {
79         unsafe {
80             transmute(rusti::atomic_xchg_rel(transmute(dst), src as isize))
81         }
82     }
83
84     pub fn send<T:Send>(mut p: send_packet<T>, payload: T) {
85         let p = p.unwrap();
86         let mut p = unsafe { uniquify(p) };
87         assert!((*p).payload.is_none());
88         (*p).payload = Some(payload);
89         let old_state = swap_state_rel(&mut (*p).state, full);
90         match old_state {
91           empty => {
92             // Yay, fastpath.
93
94             // The receiver will eventually clean this up.
95             unsafe { forget(p); }
96           }
97           full => { panic!("duplicate send") }
98           blocked => {
99
100             // The receiver will eventually clean this up.
101             unsafe { forget(p); }
102           }
103           terminated => {
104             // The receiver will never receive this. Rely on drop_glue
105             // to clean everything up.
106           }
107         }
108     }
109
110     pub fn recv<T:Send>(mut p: recv_packet<T>) -> Option<T> {
111         let p = p.unwrap();
112         let mut p = unsafe { uniquify(p) };
113         loop {
114             let old_state = swap_state_acq(&mut (*p).state,
115                                            blocked);
116             match old_state {
117               empty | blocked => { thread::yield_now(); }
118               full => {
119                 let payload = replace(&mut p.payload, None);
120                 return Some(payload.unwrap())
121               }
122               terminated => {
123                 assert_eq!(old_state, terminated);
124                 return None;
125               }
126             }
127         }
128     }
129
130     pub fn sender_terminate<T:Send>(p: *const packet<T>) {
131         let mut p = unsafe { uniquify(p) };
132         match swap_state_rel(&mut (*p).state, terminated) {
133           empty | blocked => {
134             // The receiver will eventually clean up.
135             unsafe { forget(p) }
136           }
137           full => {
138             // This is impossible
139             panic!("you dun goofed")
140           }
141           terminated => {
142             // I have to clean up, use drop_glue
143           }
144         }
145     }
146
147     pub fn receiver_terminate<T:Send>(p: *const packet<T>) {
148         let mut p = unsafe { uniquify(p) };
149         match swap_state_rel(&mut (*p).state, terminated) {
150           empty => {
151             // the sender will clean up
152             unsafe { forget(p) }
153           }
154           blocked => {
155             // this shouldn't happen.
156             panic!("terminating a blocked packet")
157           }
158           terminated | full => {
159             // I have to clean up, use drop_glue
160           }
161         }
162     }
163
164     pub struct send_packet<T:Send> {
165         p: Option<*const packet<T>>,
166     }
167
168     impl<T:Send> Drop for send_packet<T> {
169         fn drop(&mut self) {
170             unsafe {
171                 if self.p != None {
172                     let self_p: &mut Option<*const packet<T>> =
173                         mem::transmute(&mut self.p);
174                     let p = replace(self_p, None);
175                     sender_terminate(p.unwrap())
176                 }
177             }
178         }
179     }
180
181     impl<T:Send> send_packet<T> {
182         pub fn unwrap(&mut self) -> *const packet<T> {
183             replace(&mut self.p, None).unwrap()
184         }
185     }
186
187     pub fn send_packet<T:Send>(p: *const packet<T>) -> send_packet<T> {
188         send_packet {
189             p: Some(p)
190         }
191     }
192
193     pub struct recv_packet<T:Send> {
194         p: Option<*const packet<T>>,
195     }
196
197     impl<T:Send> Drop for recv_packet<T> {
198         fn drop(&mut self) {
199             unsafe {
200                 if self.p != None {
201                     let self_p: &mut Option<*const packet<T>> =
202                         mem::transmute(&mut self.p);
203                     let p = replace(self_p, None);
204                     receiver_terminate(p.unwrap())
205                 }
206             }
207         }
208     }
209
210     impl<T:Send> recv_packet<T> {
211         pub fn unwrap(&mut self) -> *const packet<T> {
212             replace(&mut self.p, None).unwrap()
213         }
214     }
215
216     pub fn recv_packet<T:Send>(p: *const packet<T>) -> recv_packet<T> {
217         recv_packet {
218             p: Some(p)
219         }
220     }
221
222     pub fn entangle<T:Send>() -> (send_packet<T>, recv_packet<T>) {
223         let p = packet();
224         (send_packet(p), recv_packet(p))
225     }
226 }
227
228 pub mod pingpong {
229     use std::mem;
230
231     pub struct ping(::pipes::send_packet<pong>);
232
233     unsafe impl Send for ping {}
234
235     pub struct pong(::pipes::send_packet<ping>);
236
237     unsafe impl Send for pong {}
238
239     pub fn liberate_ping(p: ping) -> ::pipes::send_packet<pong> {
240         unsafe {
241             let _addr : *const ::pipes::send_packet<pong> = match &p {
242               &ping(ref x) => { mem::transmute(x) }
243             };
244             panic!()
245         }
246     }
247
248     pub fn liberate_pong(p: pong) -> ::pipes::send_packet<ping> {
249         unsafe {
250             let _addr : *const ::pipes::send_packet<ping> = match &p {
251               &pong(ref x) => { mem::transmute(x) }
252             };
253             panic!()
254         }
255     }
256
257     pub fn init() -> (client::ping, server::ping) {
258         ::pipes::entangle()
259     }
260
261     pub mod client {
262         use pingpong;
263
264         pub type ping = ::pipes::send_packet<pingpong::ping>;
265         pub type pong = ::pipes::recv_packet<pingpong::pong>;
266
267         pub fn do_ping(c: ping) -> pong {
268             let (sp, rp) = ::pipes::entangle();
269
270             ::pipes::send(c, pingpong::ping(sp));
271             rp
272         }
273
274         pub fn do_pong(c: pong) -> (ping, ()) {
275             let packet = ::pipes::recv(c);
276             if packet.is_none() {
277                 panic!("sender closed the connection")
278             }
279             (pingpong::liberate_pong(packet.unwrap()), ())
280         }
281     }
282
283     pub mod server {
284         use pingpong;
285
286         pub type ping = ::pipes::recv_packet<pingpong::ping>;
287         pub type pong = ::pipes::send_packet<pingpong::pong>;
288
289         pub fn do_ping(c: ping) -> (pong, ()) {
290             let packet = ::pipes::recv(c);
291             if packet.is_none() {
292                 panic!("sender closed the connection")
293             }
294             (pingpong::liberate_ping(packet.unwrap()), ())
295         }
296
297         pub fn do_pong(c: pong) -> ping {
298             let (sp, rp) = ::pipes::entangle();
299             ::pipes::send(c, pingpong::pong(sp));
300             rp
301         }
302     }
303 }
304
305 fn client(chan: pingpong::client::ping) {
306     let chan = pingpong::client::do_ping(chan);
307     println!("Sent ping");
308     let (_chan, _data) = pingpong::client::do_pong(chan);
309     println!("Received pong");
310 }
311
312 fn server(chan: pingpong::server::ping) {
313     let (chan, _data) = pingpong::server::do_ping(chan);
314     println!("Received ping");
315     let _chan = pingpong::server::do_pong(chan);
316     println!("Sent pong");
317 }
318
319 pub fn main() {
320   /*
321 //    Commented out because of option::get error
322
323     let (client_, server_) = pingpong::init();
324
325     task::spawn {|client_|
326         let client__ = client_.take();
327         client(client__);
328     };
329     task::spawn {|server_|
330         let server__ = server_.take();
331         server(server_ˊ);
332     };
333   */
334 }