Skip to content

Commit e7a2b7f

Browse files
committed
---
yaml --- r: 12735 b: refs/heads/master c: beb1a59 h: refs/heads/master i: 12733: d634511 12731: 52258cc 12727: 59774e7 12719: a26ee9f 12703: b5cb19f 12671: 7820964 v: v3
1 parent 46e5c7c commit e7a2b7f

File tree

4 files changed

+74
-1
lines changed

4 files changed

+74
-1
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 29b807be2a0d060e4321b28849e68596dc1a6b45
2+
refs/heads/master: beb1a59f82e7689b72bf10d2a86d0d1b6060983e
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 4a81779abd786ff22d71434c6d9a5917ea4cdfff
55
refs/heads/try: 2898dcc5d97da9427ac367542382b6239d9c0bbf

trunk/src/libcore/comm.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import either::either;
2828

2929
export send;
3030
export recv;
31+
export recv_chan;
3132
export peek;
3233
export select2;
3334
export chan::{};
@@ -52,6 +53,10 @@ native mod rustrt {
5253
fn rust_port_select(dptr: **rust_port, ports: **rust_port,
5354
n_ports: libc::size_t,
5455
yield: *libc::uintptr_t);
56+
fn rust_port_take(port_id: port_id) -> *rust_port;
57+
fn rust_port_drop(p: *rust_port);
58+
fn rust_port_task(p: *rust_port) -> libc::uintptr_t;
59+
fn get_task_id() -> libc::uintptr_t;
5560
}
5661

5762
#[abi = "rust-intrinsic"]
@@ -132,6 +137,25 @@ task will block until data becomes available.
132137
"]
133138
fn recv<T: send>(p: port<T>) -> T { recv_(***p) }
134139

140+
#[doc(hidden)]
141+
fn recv_chan<T: send>(ch: comm::chan<T>) -> T {
142+
resource portref(p: *rust_port) {
143+
if !ptr::is_null(p) {
144+
rustrt::rust_port_drop(p);
145+
}
146+
}
147+
148+
let p = portref(rustrt::rust_port_take(*ch));
149+
150+
if ptr::is_null(*p) {
151+
fail "unable to locate port for channel"
152+
} else if rustrt::get_task_id() != rustrt::rust_port_task(*p) {
153+
fail "attempting to receive on unowned channel"
154+
}
155+
156+
recv_(*p)
157+
}
158+
135159
#[doc = "Receive on a raw port pointer"]
136160
fn recv_<T: send>(p: *rust_port) -> T {
137161
let yield = 0u;
@@ -327,3 +351,31 @@ fn test_select2_stress() {
327351
assert as == 400;
328352
assert bs == 400;
329353
}
354+
355+
#[test]
356+
fn test_recv_chan() {
357+
let po = port();
358+
let ch = chan(po);
359+
send(ch, "flower");
360+
assert recv_chan(ch) == "flower";
361+
}
362+
363+
#[test]
364+
#[should_fail]
365+
#[ignore(cfg(target_os = "win32"))]
366+
fn test_recv_chan_dead() {
367+
let ch = chan(port());
368+
send(ch, "flower");
369+
recv_chan(ch);
370+
}
371+
372+
#[test]
373+
#[ignore(cfg(target_os = "win32"))]
374+
fn test_recv_chan_wrong_task() {
375+
let po = port();
376+
let ch = chan(po);
377+
send(ch, "flower");
378+
assert result::is_failure(task::try {||
379+
recv_chan(ch)
380+
})
381+
}

trunk/src/rt/rust_builtin.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,24 @@ sched_threads() {
630630
return task->sched->number_of_threads();
631631
}
632632

633+
extern "C" CDECL rust_port*
634+
rust_port_take(rust_port_id id) {
635+
rust_task *task = rust_get_current_task();
636+
return task->kernel->get_port_by_id(id);
637+
}
638+
639+
extern "C" CDECL void
640+
rust_port_drop(rust_port *p) {
641+
assert(p != NULL);
642+
p->deref();
643+
}
644+
645+
extern "C" CDECL rust_task_id
646+
rust_port_task(rust_port *p) {
647+
assert(p != NULL);
648+
return p->task->id;
649+
}
650+
633651
extern "C" CDECL rust_port*
634652
new_port(size_t unit_sz) {
635653
rust_task *task = rust_get_current_task();

trunk/src/rt/rustrt.def.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,6 @@ rust_dbg_call
149149
rust_osmain_sched_id
150150
rust_compare_and_swap_ptr
151151
rust_global_env_chan_ptr
152+
rust_port_take
153+
rust_port_drop
154+
rust_port_task

0 commit comments

Comments
 (0)