Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sharing Channels in Rust #3928

Closed
jhebus opened this issue Nov 6, 2012 · 5 comments
Closed

Sharing Channels in Rust #3928

jhebus opened this issue Nov 6, 2012 · 5 comments

Comments

@jhebus
Copy link

jhebus commented Nov 6, 2012

Hi,

I'm new to Rust and trying to figure out how to use it. In the following code i am trying to create some channels in main and then disperse them to some tasks, but the (0.4) compiler is telling me that i am not able to copy channels or ports. So,

*Is what i am trying to do possible
*Is there a better way

Thanks,

Paul

/-------------------------------------/

use pipes::;
use io::
;

fn recv_actor(b: Port<~str>) {

loop{
    let val = b.recv();
    println(#fmt("%s", val));
}

}

fn send_actor(a: Chan<~str>) {

loop{
    let readBytes = io::stdin().read_line();    
    a.send(readBytes);
}

}

fn main() {
let (a, b) = stream();

do task::spawn | move a|{ send_actor(a); }
do task::spawn | move b|{ recv_actor(b); }

}

@eholk
Copy link
Contributor

eholk commented Nov 6, 2012

There is also a SharedChan in the pipes module which you can create from a Chan. This has a .clone() method which can be used to make copies that can be sent to multiple tasks.

You might also try the PortSet object too. They both give you similar functionality (that is, enabling many senders to one receiver), but they put the complexity in different places. SharedChan puts more contention on the sender side, so it's good when you have many senders who send infrequently. PortSet puts the complexity on the receiver side, so this works better when you have senders that need to send frequently.

@jhebus
Copy link
Author

jhebus commented Nov 7, 2012

Hi, thanks for the reply.

The shared channel worked fine, but only if the clone was created within the task. Why am i not allowed to pass the clone into the task?

let chan = SharedChan(move chan);

do task::spawn {
let a = chan.clone();
send_actor(a);
}

Also, is there an equivalent that will enable me to share ports?

On a more fundamental note, is there any language level reason that channels and ports are not always shared/share-able. I assume that it has something to do with the memory model.

Also, it is possible to have a third party bind two channels together, for example a channel and a port are passed to a function, and that function can then join them together? I saw in the documentation that this seems not to be the case, but i thought i would ask in case things have changed?

@eholk
Copy link
Contributor

eholk commented Nov 7, 2012

The following should work:

let chan = SharedChan(move chan);

let a = chan.clone();

do task::spawn |move a| {
    send_actor(a);
}

The |move a| clause might be unnecessary... Anyway, this should let you continue to make clones of chan to share with other tasks.

By binding channels together, do you mean connecting a port to a chan so that data sent to the port is automatically forwarded to the chan? If so, this isn't possible. You could spawn another task that just does the forwarding on its own. It might be possible to do some more direct binding, but I'm not sure.

As far as why ports and chans are not always copyable, this has to do with the extra assumptions we can make when we have 1:1 communication. It's a lot easier to reason about pipe protocols (which are admittedly a somewhat advanced feature) when there are only two parties participating. We can also get a more efficient implementation because the synchronization logic can be greatly simplified with only one sender and one receiver.

@jhebus
Copy link
Author

jhebus commented Nov 7, 2012

I changed my main to be as you suggested above (also removed the second spawn for the moment), however either with or without the "move a" the compiler still complains that the cloned channel is not copyable when used with the send_actor().

I still don't seem to be able to find a way to pass a port to a function within and channel. Is this possible, as in the variable "b" in my original example?

By binding together i mean, it is possible to from dynamic topologies of channels and ports at runtime; Individually creating channels and ports, then forming connections between them at some later (optional) stage. Although, from your later description this does not sound possible.

How can i determine when a channel/port is or is not copyable?

@catamorphism
Copy link
Contributor

Closing this because it seems like more of an informational question than a bug report. @jhebus , please feel free to continue this discussion on the mailing list or IRC channel :-)

RalfJung pushed a commit to RalfJung/rust that referenced this issue Oct 5, 2024
…li-obk

Add vector clock to epoll ready lists

Replaces rust-lang#3928

Fixes rust-lang#3911
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants