Live data from Hacker News

Concurrency in Rust

doc.rust-lang.org

31–40 of 160 posts

Re: Concurrency in Rust

#32

Send + Sync are great. The downside of concurrency in Rust is: 1) There isn't transparent integration with IO in the runtime as in Go or Haskell. Rust probably won't ever do this because although such a model scales well in general, it does create overhead and a runtime. 2) OS threads are difficult to work with compared to a nice M:N threading abstraction (which again are the default in Go or Haskell). OS threads lea…

There's no way to kill goroutines either. In fact, are there any systems that allow you to cleanly kill threads?

Re: Concurrency in Rust

#33
post #15

Earlier quoted context omitted.

So, for those who may know JavaScript, you may have seen code like this: var closures = []; for (var i=0;i The code above will result in incorrect results: 5, 5, 5, 5, 5. Because you're capturing `i` as a reference. To avoid this, JS devs typically do this: closures.push((function(i) { return function() { console.log(i); }; })(i)); Or, if you can afford the ES6 support: for (let i=0;i Rust supports this pattern by a…

The ES6 "fix" is an abomination in my opinion. You're closing over a mutable variable, so you should see the mutations! IMO the real fix would be to write for (var i = 0; i In your ES6 solution if you e.g. increment "i" inside the loop after the closure the closure will see the mutation! The real cause of confusion is mutation and javascript's scoping rules.

If you write `let data = data;` in the closure, then you can achieve the effect of `move` without the special syntax (unless `data` can be copied, in which case there is really no way to force it to be moved inside the closure without `move`).

However, in Rust, you get an error if you accidentally capture by reference in the closure passed to `thread::spawn` so it's not as hard to get right as it is in JS.

Re: Concurrency in Rust

#34

Send + Sync are great. The downside of concurrency in Rust is: 1) There isn't transparent integration with IO in the runtime as in Go or Haskell. Rust probably won't ever do this because although such a model scales well in general, it does create overhead and a runtime. 2) OS threads are difficult to work with compared to a nice M:N threading abstraction (which again are the default in Go or Haskell). OS threads lea…

There's no way to kill goroutines either. In fact, are there any systems that allow you to cleanly kill threads?

Every one I know of has regretted it, and seen it as an antipattern. For example, Java way back in 1.5: http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPr...

I think Erlang might be okay with it, because "this thread can fail at any time" is a core value of Erlang. But it's an exception.

Re: Concurrency in Rust

#35

Send + Sync are great. The downside of concurrency in Rust is: 1) There isn't transparent integration with IO in the runtime as in Go or Haskell. Rust probably won't ever do this because although such a model scales well in general, it does create overhead and a runtime. 2) OS threads are difficult to work with compared to a nice M:N threading abstraction (which again are the default in Go or Haskell). OS threads lea…

There's no way to kill goroutines either. In fact, are there any systems that allow you to cleanly kill threads?

[deleted]

Re: Concurrency in Rust

#36

Send + Sync are great. The downside of concurrency in Rust is: 1) There isn't transparent integration with IO in the runtime as in Go or Haskell. Rust probably won't ever do this because although such a model scales well in general, it does create overhead and a runtime. 2) OS threads are difficult to work with compared to a nice M:N threading abstraction (which again are the default in Go or Haskell). OS threads lea…

There's no way to kill goroutines either. In fact, are there any systems that allow you to cleanly kill threads?

Yes.

In Erlang:

    exit(kill).
or exit(Pid,kill).

Will kill a process. It has an isolated heap, so it won't affect other (possibly hundreds of thousands of) running processes. That memory will be garbage collected, safely and efficiently.

This will also work in Elixir, LFE and other languages running on the BEAM VM platform.

EDIT: masklinn user below pointed out correctly, the example is exit/2, that is exit(Pid,kill). In fact it is just exit(Pid, Reason), where Reason can be other exit reason, like say my_socket_failed. However in that case the process could catch it and handle that signal instead of being un-conditionally killed.

Re: Concurrency in Rust

#37
post #2

I think Steve Klabnik could clarify this, but the book at that link is in the process of being rewritten. I think it might be good to wait until it is. I personally found it slightly difficult to follow compared to other options like the soon to be published Programming Rust.

I am in the middle of working on a second draft of the book. This page is one of the oldest bits of docs, overall, and isn't my best work. It's not _wrong_, I just have very high personal standards. It was adapted from older documentation and was written in the time up to 1.0, where I had a LOT on my plate.

Re: Concurrency in Rust

#38
post #7
post #4

I'm having a tough time trying to understand this snippet for i in 0..3 { thread::spawn(move || { data[i] += 1; }); } What is the 'move' thing here before the ||

A move closure takes copies of the environment, instead of mutating the parent environment. https://doc.rust-lang.org/book/closures.html#move-closures

But isn't it confusing that it is called "move" instead of "copy" if it takes copies?

Re: Concurrency in Rust

#39
post #18
post #15

Earlier quoted context omitted.

So, for those who may know JavaScript, you may have seen code like this: var closures = []; for (var i=0;i The code above will result in incorrect results: 5, 5, 5, 5, 5. Because you're capturing `i` as a reference. To avoid this, JS devs typically do this: closures.push((function(i) { return function() { console.log(i); }; })(i)); Or, if you can afford the ES6 support: for (let i=0;i Rust supports this pattern by a…

Thanks for the explanation, but how would the move keyword know that you're referring to the i variable? Ie - what is there were multiple variables (such as a for loop with j in there)? Wouldn't it have been a better approach to add some sort of demarkation, such as i* or i^ (or whatever) to indicate this? Just curious.

In short, the "move everything" nature of "move" keyword here is not an issue because you can just make references for items you don't want moved. References themselves are "moved" by just copying their addresses.

Re: Concurrency in Rust

#40
post #38
post #7

Earlier quoted context omitted.

A move closure takes copies of the environment, instead of mutating the parent environment. https://doc.rust-lang.org/book/closures.html#move-closures

But isn't it confusing that it is called "move" instead of "copy" if it takes copies?

Move and Copy are identical at the assembly level. The only difference is what you can do with the older binding. Semantically speaking, both cause a memcpy, though the optimizer may elide them.

That said, you're right that saying "copy" is misleading, for this reason. But moves _are_ a kind of copy.

Post reply on HN