Skip to content

Commit eff7f56

Browse files
committed
---
yaml --- r: 20790 b: refs/heads/snap-stage3 c: 7192761 h: refs/heads/master v: v3
1 parent 270873e commit eff7f56

File tree

9 files changed

+92
-278
lines changed

9 files changed

+92
-278
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: e430a699f2c60890d9b86069fd0c68a70ece7120
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: e7a69fbe4e33602dd6f78d140aafa5125b8eec71
4+
refs/heads/snap-stage3: 71927615e0a2cd2d9f96038ba0f403a4d833a2f5
55
refs/heads/try: ffbe0e0e00374358b789b0037bcb3a577cd218be
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b

branches/snap-stage3/src/libcore/pipes.rs

Lines changed: 16 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,4 @@
1-
/*! Runtime support for message passing with protocol enforcement.
2-
3-
4-
Pipes consist of two endpoints. One endpoint can send messages and
5-
the other can receive messages. The set of legal messages and which
6-
directions they can flow at any given point are determined by a
7-
protocol. Below is an example protocol.
8-
9-
~~~
10-
proto! pingpong {
11-
ping: send {
12-
ping -> pong
13-
}
14-
pong: recv {
15-
pong -> ping
16-
}
17-
}
18-
~~~
19-
20-
The `proto!` syntax extension will convert this into a module called
21-
`pingpong`, which includes a set of types and functions that can be
22-
used to write programs that follow the pingpong protocol.
23-
24-
*/
25-
26-
/* IMPLEMENTATION NOTES
27-
28-
The initial design for this feature is available at:
29-
30-
https://github.com/eholk/rust/wiki/Proposal-for-channel-contracts
31-
32-
Much of the design in that document is still accurate. There are
33-
several components for the pipe implementation. First of all is the
34-
syntax extension. To see how that works, it is best see comments in
35-
libsyntax/ext/pipes.rs.
36-
37-
This module includes two related pieces of the runtime
38-
implementation. There is support for unbounded and bounded
39-
protocols. The main difference between the two is the type of the
40-
buffer that is carried along in the endpoint data structures.
41-
42-
FIXME (#3072) - This is still incomplete
43-
44-
*/
1+
// Runtime support for pipes.
452

463
import unsafe::{forget, reinterpret_cast, transmute};
474
import either::{either, left, right};
@@ -54,7 +11,7 @@ export send_packet_buffered, recv_packet_buffered;
5411
export packet, mk_packet, entangle_buffer, has_buffer, buffer_header;
5512

5613
// export these so we can find them in the buffer_resource
57-
// destructor. This is probably a symptom of #3005.
14+
// destructor. This is probably another metadata bug.
5815
export atomic_add_acq, atomic_sub_rel;
5916

6017
// User-level things
@@ -63,22 +20,24 @@ export select, select2, selecti, select2i, selectable;
6320
export spawn_service, spawn_service_recv;
6421
export stream, port, chan, shared_chan, port_set, channel;
6522

66-
#[doc(hidden)]
6723
const SPIN_COUNT: uint = 0;
6824

6925
macro_rules! move_it {
7026
{ $x:expr } => { unsafe { let y <- *ptr::addr_of($x); y } }
7127
}
7228

73-
#[doc(hidden)]
29+
// This is to help make sure we only move out of enums in safe
30+
// places. Once there is unary move, it can be removed.
31+
fn move_it<T>(-x: T) -> T { x }
32+
7433
enum state {
7534
empty,
7635
full,
7736
blocked,
7837
terminated
7938
}
8039

81-
struct buffer_header {
40+
class buffer_header {
8241
// Tracks whether this buffer needs to be freed. We can probably
8342
// get away with restricting it to 0 or 1, if we're careful.
8443
let mut ref_count: int;
@@ -90,13 +49,12 @@ struct buffer_header {
9049
}
9150

9251
// This is for protocols to associate extra data to thread around.
93-
#[doc(hidden)]
9452
type buffer<T: send> = {
9553
header: buffer_header,
9654
data: T,
9755
};
9856

99-
struct packet_header {
57+
class packet_header {
10058
let mut state: state;
10159
let mut blocked_task: option<*rust_task>;
10260

@@ -137,7 +95,6 @@ struct packet_header {
13795
}
13896
}
13997

140-
#[doc(hidden)]
14198
type packet<T: send> = {
14299
header: packet_header,
143100
mut payload: option<T>,
@@ -176,7 +133,6 @@ fn unibuffer<T: send>() -> ~buffer<packet<T>> {
176133
b
177134
}
178135

179-
#[doc(hidden)]
180136
fn packet<T: send>() -> *packet<T> {
181137
let b = unibuffer();
182138
let p = ptr::addr_of(b.data);
@@ -185,7 +141,6 @@ fn packet<T: send>() -> *packet<T> {
185141
p
186142
}
187143

188-
#[doc(hidden)]
189144
fn entangle_buffer<T: send, Tstart: send>(
190145
-buffer: ~buffer<T>,
191146
init: fn(*libc::c_void, x: &T) -> *packet<Tstart>)
@@ -208,22 +163,18 @@ extern mod rusti {
208163

209164
// If I call the rusti versions directly from a polymorphic function,
210165
// I get link errors. This is a bug that needs investigated more.
211-
#[doc(hidden)]
212166
fn atomic_xchng_rel(&dst: int, src: int) -> int {
213167
rusti::atomic_xchng_rel(dst, src)
214168
}
215169

216-
#[doc(hidden)]
217170
fn atomic_add_acq(&dst: int, src: int) -> int {
218171
rusti::atomic_add_acq(dst, src)
219172
}
220173

221-
#[doc(hidden)]
222174
fn atomic_sub_rel(&dst: int, src: int) -> int {
223175
rusti::atomic_sub_rel(dst, src)
224176
}
225177

226-
#[doc(hidden)]
227178
type rust_task = libc::c_void;
228179

229180
extern mod rustrt {
@@ -237,7 +188,6 @@ extern mod rustrt {
237188
pure fn task_signal_event(target: *rust_task, event: *libc::c_void);
238189
}
239190

240-
#[doc(hidden)]
241191
fn wait_event(this: *rust_task) -> *libc::c_void {
242192
let mut event = ptr::null();
243193

@@ -248,7 +198,6 @@ fn wait_event(this: *rust_task) -> *libc::c_void {
248198
event
249199
}
250200

251-
#[doc(hidden)]
252201
fn swap_state_acq(&dst: state, src: state) -> state {
253202
unsafe {
254203
reinterpret_cast(rusti::atomic_xchng_acq(
@@ -257,7 +206,6 @@ fn swap_state_acq(&dst: state, src: state) -> state {
257206
}
258207
}
259208

260-
#[doc(hidden)]
261209
fn swap_state_rel(&dst: state, src: state) -> state {
262210
unsafe {
263211
reinterpret_cast(rusti::atomic_xchng_rel(
@@ -266,12 +214,11 @@ fn swap_state_rel(&dst: state, src: state) -> state {
266214
}
267215
}
268216

269-
#[doc(hidden)]
270217
unsafe fn get_buffer<T: send>(p: *packet_header) -> ~buffer<T> {
271218
transmute((*p).buf_header())
272219
}
273220

274-
struct buffer_resource<T: send> {
221+
class buffer_resource<T: send> {
275222
let buffer: ~buffer<T>;
276223
new(+b: ~buffer<T>) {
277224
//let p = ptr::addr_of(*b);
@@ -297,7 +244,6 @@ struct buffer_resource<T: send> {
297244
}
298245
}
299246

300-
#[doc(hidden)]
301247
fn send<T: send, Tbuffer: send>(-p: send_packet_buffered<T, Tbuffer>,
302248
-payload: T) {
303249
let header = p.header();
@@ -335,21 +281,10 @@ fn send<T: send, Tbuffer: send>(-p: send_packet_buffered<T, Tbuffer>,
335281
}
336282
}
337283

338-
/** Receives a message from a pipe.
339-
340-
Fails if the sender closes the connection.
341-
342-
*/
343284
fn recv<T: send, Tbuffer: send>(-p: recv_packet_buffered<T, Tbuffer>) -> T {
344285
option::unwrap(try_recv(p))
345286
}
346287

347-
/** Attempts to receive a message from a pipe.
348-
349-
Returns `none` if the sender has closed the connection without sending
350-
a message, or `some(T)` if a message was received.
351-
352-
*/
353288
fn try_recv<T: send, Tbuffer: send>(-p: recv_packet_buffered<T, Tbuffer>)
354289
-> option<T>
355290
{
@@ -416,7 +351,6 @@ impl peek<T: send, Tb: send> for recv_packet_buffered<T, Tb> {
416351
}
417352
}
418353

419-
#[doc(hidden)]
420354
fn sender_terminate<T: send>(p: *packet<T>) {
421355
let p = unsafe { &*p };
422356
alt swap_state_rel(p.header.state, terminated) {
@@ -443,7 +377,6 @@ fn sender_terminate<T: send>(p: *packet<T>) {
443377
}
444378
}
445379

446-
#[doc(hidden)]
447380
fn receiver_terminate<T: send>(p: *packet<T>) {
448381
let p = unsafe { &*p };
449382
alt swap_state_rel(p.header.state, terminated) {
@@ -461,16 +394,8 @@ fn receiver_terminate<T: send>(p: *packet<T>) {
461394
}
462395
}
463396

464-
/** Returns when one of the packet headers reports data is available.
465-
466-
This function is primarily intended for building higher level waiting
467-
functions, such as `select`, `select2`, etc.
468-
469-
It takes a vector slice of packet_headers and returns an index into
470-
that vector. The index points to an endpoint that has either been
471-
closed by the sender or has a message waiting to be received.
472-
473-
*/
397+
#[doc = "Returns when one of the packet headers reports data is
398+
available."]
474399
fn wait_many(pkts: &[*packet_header]) -> uint {
475400
let this = rustrt::rust_get_task();
476401

@@ -522,34 +447,6 @@ fn wait_many(pkts: &[*packet_header]) -> uint {
522447
ready_packet
523448
}
524449

525-
/** Receives a message from one of two endpoints.
526-
527-
The return value is `left` if the first endpoint received something,
528-
or `right` if the second endpoint receives something. In each case,
529-
the result includes the other endpoint as well so it can be used
530-
again. Below is an example of using `select2`.
531-
532-
~~~
533-
match select2(a, b) {
534-
left((none, b)) {
535-
// endpoint a was closed.
536-
}
537-
right((a, none)) {
538-
// endpoint b was closed.
539-
}
540-
left((some(_), b)) {
541-
// endpoint a received a message
542-
}
543-
right(a, some(_)) {
544-
// endpoint b received a message.
545-
}
546-
}
547-
~~~
548-
549-
Sometimes messages will be available on both endpoints at once. In
550-
this case, `select2` may return either `left` or `right`.
551-
552-
*/
553450
fn select2<A: send, Ab: send, B: send, Bb: send>(
554451
+a: recv_packet_buffered<A, Ab>,
555452
+b: recv_packet_buffered<B, Bb>)
@@ -603,16 +500,13 @@ fn select<T: send, Tb: send>(+endpoints: ~[recv_packet_buffered<T, Tb>])
603500
(ready, result, remaining)
604501
}
605502

606-
/// The sending end of a pipe. It can be used to send exactly one
607-
/// message.
608503
type send_packet<T: send> = send_packet_buffered<T, packet<T>>;
609504

610-
#[doc(hidden)]
611505
fn send_packet<T: send>(p: *packet<T>) -> send_packet<T> {
612506
send_packet_buffered(p)
613507
}
614508

615-
struct send_packet_buffered<T: send, Tbuffer: send> {
509+
class send_packet_buffered<T: send, Tbuffer: send> {
616510
let mut p: option<*packet<T>>;
617511
let mut buffer: option<buffer_resource<Tbuffer>>;
618512
new(p: *packet<T>) {
@@ -666,16 +560,13 @@ struct send_packet_buffered<T: send, Tbuffer: send> {
666560
}
667561
}
668562

669-
/// Represents the receive end of a pipe. It can receive exactly one
670-
/// message.
671563
type recv_packet<T: send> = recv_packet_buffered<T, packet<T>>;
672564

673-
#[doc(hidden)]
674565
fn recv_packet<T: send>(p: *packet<T>) -> recv_packet<T> {
675566
recv_packet_buffered(p)
676567
}
677568

678-
struct recv_packet_buffered<T: send, Tbuffer: send> : selectable {
569+
class recv_packet_buffered<T: send, Tbuffer: send> : selectable {
679570
let mut p: option<*packet<T>>;
680571
let mut buffer: option<buffer_resource<Tbuffer>>;
681572
new(p: *packet<T>) {
@@ -729,7 +620,6 @@ struct recv_packet_buffered<T: send, Tbuffer: send> : selectable {
729620
}
730621
}
731622

732-
#[doc(hidden)]
733623
fn entangle<T: send>() -> (send_packet<T>, recv_packet<T>) {
734624
let p = packet();
735625
(send_packet(p), recv_packet(p))
@@ -796,14 +686,12 @@ trait recv<T: send> {
796686
pure fn peek() -> bool;
797687
}
798688

799-
#[doc(hidden)]
800689
type chan_<T:send> = { mut endp: option<streamp::client::open<T>> };
801690

802691
enum chan<T:send> {
803692
chan_(chan_<T>)
804693
}
805694

806-
#[doc(hidden)]
807695
type port_<T:send> = { mut endp: option<streamp::server::open<T>> };
808696

809697
enum port<T:send> {
@@ -837,7 +725,7 @@ impl port<T: send> of recv<T> for port<T> {
837725
fn try_recv() -> option<T> {
838726
let mut endp = none;
839727
endp <-> self.endp;
840-
alt move pipes::try_recv(unwrap(endp)) {
728+
alt move_it(pipes::try_recv(unwrap(endp))) {
841729
some(streamp::data(x, endp)) {
842730
self.endp = some(move_it!{endp});
843731
some(move_it!{x})
@@ -861,7 +749,7 @@ impl port<T: send> of recv<T> for port<T> {
861749
}
862750

863751
// Treat a whole bunch of ports as one.
864-
struct port_set<T: send> : recv<T> {
752+
class port_set<T: send> : recv<T> {
865753
let mut ports: ~[pipes::port<T>];
866754

867755
new() { self.ports = ~[]; }
@@ -882,7 +770,7 @@ struct port_set<T: send> : recv<T> {
882770
let i = wait_many(self.ports.map(|p| p.header()));
883771
// dereferencing an unsafe pointer nonsense to appease the
884772
// borrowchecker.
885-
alt move unsafe {(*ptr::addr_of(self.ports[i])).try_recv()} {
773+
alt move_it(unsafe {(*ptr::addr_of(self.ports[i])).try_recv()}) {
886774
some(m) {
887775
result = some(move_it!{m});
888776
}

0 commit comments

Comments
 (0)