Skip to content

Commit 7abcc14

Browse files
committed
auto merge of #6626 : brson/rust/io-upstream, r=graydon
r? Mostly refactoring, and adding some of the remaining types described in #4419. The [`Local`](https://github.com/brson/rust/blob/3b4ff41511cfaa5e311b03d16b47bf40c117fa2f/src/libcore/rt/local.rs#L17) trait collects some common, often unsafe patterns around task-local and thread-local values. Making all these types safe is largely the aim of #6210.
2 parents adaae45 + a246e8f commit 7abcc14

20 files changed

+466
-321
lines changed

src/libcore/logging.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,11 @@ pub fn log_type<T>(level: u32, object: &T) {
6666
}
6767

6868
fn newsched_log_str(msg: ~str) {
69+
use rt::task::Task;
70+
use rt::local::Local;
71+
6972
unsafe {
70-
match rt::local_services::unsafe_try_borrow_local_services() {
73+
match Local::try_unsafe_borrow::<Task>() {
7174
Some(local) => {
7275
// Use the available logger
7376
(*local).logger.log(Left(msg));

src/libcore/rt/comm.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use cast;
2020
use util;
2121
use ops::Drop;
2222
use kinds::Owned;
23-
use rt::sched::Coroutine;
24-
use rt::local_sched;
23+
use rt::sched::{Scheduler, Coroutine};
24+
use rt::local::Local;
2525
use unstable::intrinsics::{atomic_xchg, atomic_load};
2626
use util::Void;
2727
use comm::{GenericChan, GenericSmartChan, GenericPort, Peekable};
@@ -127,7 +127,7 @@ impl<T> ChanOne<T> {
127127
task_as_state => {
128128
// Port is blocked. Wake it up.
129129
let recvr: ~Coroutine = cast::transmute(task_as_state);
130-
let sched = local_sched::take();
130+
let sched = Local::take::<Scheduler>();
131131
sched.schedule_task(recvr);
132132
}
133133
}
@@ -157,7 +157,7 @@ impl<T> PortOne<T> {
157157
// XXX: Optimize this to not require the two context switches when data is available
158158

159159
// Switch to the scheduler to put the ~Task into the Packet state.
160-
let sched = local_sched::take();
160+
let sched = Local::take::<Scheduler>();
161161
do sched.deschedule_running_task_and_then |task| {
162162
unsafe {
163163
// Atomically swap the task pointer into the Packet state, issuing
@@ -173,7 +173,7 @@ impl<T> PortOne<T> {
173173
STATE_ONE => {
174174
// Channel is closed. Switch back and check the data.
175175
let task: ~Coroutine = cast::transmute(task_as_state);
176-
let sched = local_sched::take();
176+
let sched = Local::take::<Scheduler>();
177177
sched.resume_task_immediately(task);
178178
}
179179
_ => util::unreachable()
@@ -239,7 +239,7 @@ impl<T> Drop for ChanOneHack<T> {
239239
// The port is blocked waiting for a message we will never send. Wake it.
240240
assert!((*this.packet()).payload.is_none());
241241
let recvr: ~Coroutine = cast::transmute(task_as_state);
242-
let sched = local_sched::take();
242+
let sched = Local::take::<Scheduler>();
243243
sched.schedule_task(recvr);
244244
}
245245
}

src/libcore/rt/io/net/tcp.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010

1111
use option::{Option, Some, None};
1212
use result::{Ok, Err};
13-
use rt::sched::local_sched::unsafe_borrow_io;
1413
use rt::io::net::ip::IpAddr;
1514
use rt::io::{Reader, Writer, Listener};
1615
use rt::io::{io_error, read_error, EndOfFile};
17-
use rt::rtio::{IoFactory,
16+
use rt::rtio::{IoFactory, IoFactoryObject,
1817
RtioTcpListener, RtioTcpListenerObject,
1918
RtioTcpStream, RtioTcpStreamObject};
19+
use rt::local::Local;
2020

2121
pub struct TcpStream {
2222
rtstream: ~RtioTcpStreamObject
@@ -32,7 +32,7 @@ impl TcpStream {
3232
pub fn connect(addr: IpAddr) -> Option<TcpStream> {
3333
let stream = unsafe {
3434
rtdebug!("borrowing io to connect");
35-
let io = unsafe_borrow_io();
35+
let io = Local::unsafe_borrow::<IoFactoryObject>();
3636
rtdebug!("about to connect");
3737
(*io).tcp_connect(addr)
3838
};
@@ -88,7 +88,10 @@ pub struct TcpListener {
8888

8989
impl TcpListener {
9090
pub fn bind(addr: IpAddr) -> Option<TcpListener> {
91-
let listener = unsafe { (*unsafe_borrow_io()).tcp_bind(addr) };
91+
let listener = unsafe {
92+
let io = Local::unsafe_borrow::<IoFactoryObject>();
93+
(*io).tcp_bind(addr)
94+
};
9295
match listener {
9396
Ok(l) => {
9497
Some(TcpListener {

src/libcore/rt/local.rs

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
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+
17+
pub trait Local {
18+
fn put(value: ~Self);
19+
fn take() -> ~Self;
20+
fn exists() -> bool;
21+
fn borrow(f: &fn(&mut Self));
22+
unsafe fn unsafe_borrow() -> *mut Self;
23+
unsafe fn try_unsafe_borrow() -> Option<*mut Self>;
24+
}
25+
26+
impl Local for Scheduler {
27+
fn put(value: ~Scheduler) { unsafe { local_ptr::put(value) }}
28+
fn take() -> ~Scheduler { unsafe { local_ptr::take() } }
29+
fn exists() -> bool { local_ptr::exists() }
30+
fn borrow(f: &fn(&mut Scheduler)) { unsafe { local_ptr::borrow(f) } }
31+
unsafe fn unsafe_borrow() -> *mut Scheduler { local_ptr::unsafe_borrow() }
32+
unsafe fn try_unsafe_borrow() -> Option<*mut Scheduler> { abort!("unimpl") }
33+
}
34+
35+
impl Local for Task {
36+
fn put(value: ~Task) { abort!("unimpl") }
37+
fn take() -> ~Task { abort!("unimpl") }
38+
fn exists() -> bool { abort!("unimpl") }
39+
fn borrow(f: &fn(&mut Task)) {
40+
do Local::borrow::<Scheduler> |sched| {
41+
match sched.current_task {
42+
Some(~ref mut task) => {
43+
f(&mut *task.task)
44+
}
45+
None => {
46+
abort!("no scheduler")
47+
}
48+
}
49+
}
50+
}
51+
unsafe fn unsafe_borrow() -> *mut Task {
52+
match (*Local::unsafe_borrow::<Scheduler>()).current_task {
53+
Some(~ref mut task) => {
54+
let s: *mut Task = &mut *task.task;
55+
return s;
56+
}
57+
None => {
58+
// Don't fail. Infinite recursion
59+
abort!("no scheduler")
60+
}
61+
}
62+
}
63+
unsafe fn try_unsafe_borrow() -> Option<*mut Task> {
64+
if Local::exists::<Scheduler>() {
65+
Some(Local::unsafe_borrow())
66+
} else {
67+
None
68+
}
69+
}
70+
}
71+
72+
// XXX: This formulation won't work once ~IoFactoryObject is a real trait pointer
73+
impl Local for IoFactoryObject {
74+
fn put(value: ~IoFactoryObject) { abort!("unimpl") }
75+
fn take() -> ~IoFactoryObject { abort!("unimpl") }
76+
fn exists() -> bool { abort!("unimpl") }
77+
fn borrow(f: &fn(&mut IoFactoryObject)) { abort!("unimpl") }
78+
unsafe fn unsafe_borrow() -> *mut IoFactoryObject {
79+
let sched = Local::unsafe_borrow::<Scheduler>();
80+
let io: *mut IoFactoryObject = (*sched).event_loop.io().unwrap();
81+
return io;
82+
}
83+
unsafe fn try_unsafe_borrow() -> Option<*mut IoFactoryObject> { abort!("unimpl") }
84+
}
85+
86+
#[cfg(test)]
87+
mod test {
88+
use rt::sched::Scheduler;
89+
use rt::uv::uvio::UvEventLoop;
90+
use super::*;
91+
92+
#[test]
93+
fn thread_local_scheduler_smoke_test() {
94+
let scheduler = ~UvEventLoop::new_scheduler();
95+
Local::put(scheduler);
96+
let _scheduler: ~Scheduler = Local::take();
97+
}
98+
99+
#[test]
100+
fn thread_local_scheduler_two_instances() {
101+
let scheduler = ~UvEventLoop::new_scheduler();
102+
Local::put(scheduler);
103+
let _scheduler: ~Scheduler = Local::take();
104+
let scheduler = ~UvEventLoop::new_scheduler();
105+
Local::put(scheduler);
106+
let _scheduler: ~Scheduler = Local::take();
107+
}
108+
109+
#[test]
110+
fn borrow_smoke_test() {
111+
let scheduler = ~UvEventLoop::new_scheduler();
112+
Local::put(scheduler);
113+
unsafe {
114+
let _scheduler: *mut Scheduler = Local::unsafe_borrow();
115+
}
116+
let _scheduler: ~Scheduler = Local::take();
117+
}
118+
}

0 commit comments

Comments
 (0)