Crust of Rust: Channels

Поделиться
HTML-код
  • Опубликовано: 13 окт 2024

Комментарии • 86

  • @chrisboyce5009
    @chrisboyce5009 4 года назад +97

    Thanks Jon, I really appreciate these videos. I've worked in a number of different programming domains over the years, and Rust has really challenged me to think about things differently. I've read the books and Rust by example, and while the definitions and examples always seem reasonable and make sense, it's been difficult for me to extrapolate that knowledge into the real world. I feel like it's been difficult for me to get an "intuitive" grasp on some of the core topics, so I appreciate that you explain _why_ you do certain things, and what some alternatives are. I seem to get more practical knowledge in the first 15 minutes of your videos than I have from days of my own research.

    • @jonhoo
      @jonhoo  4 года назад +31

      I'm so happy to hear that, thank you!

  • @megumin4625
    @megumin4625 2 года назад +18

    For anyone curious about `let _`, the two things about it are
    1. It is a no-op (there's no assembly for it even; for the cases where there are, there's no difference between `let _ = stmt;` vs `stmt;`)
    2. It allows you to ignore warnings (e.g. Result not used)

  • @jRsqILVOY
    @jRsqILVOY 4 года назад +51

    The use of mem::swap instead of allocating a new VecDeque was cool.

  • @simonfarre4907
    @simonfarre4907 3 года назад +11

    One of the best video resources regarding Rust. I thoroughly appreciate this.

  • @EidosGaming
    @EidosGaming 3 года назад +5

    I absolutely love these Crust of Rust rediffusions. I'm watching them all, I'll definitely try to watch one live

    • @bjugdbjk
      @bjugdbjk 2 года назад

      Can u suggest with which 1 do we need to start !! imagine a guy with basics of rust .

    • @raiguard
      @raiguard 2 года назад

      @@bjugdbjk I'd recommend iterators first. They're super helpful to know. But mostly, start building real projects and come watch a crust of rust if you need help with that concept.
      I'm working on my first multithreaded project, so I read through the multithreading part of the rust book, then came here to watch Jon's explanation of channels.

  • @nicolaswolyniec1354
    @nicolaswolyniec1354 9 месяцев назад +1

    its been a few years since the release of this video, but It helped me a lot! thanks!

  • @jasonleo
    @jasonleo 4 года назад +43

    Haha, new intro

  • @darrennew8211
    @darrennew8211 4 года назад +5

    I'm pretty sure you want to signal the condition variable while you still hold the lock. Don't drop the lock guard before signalling the condition variable. (That's sort of how condition variables work in every language.) Otherwise, you can wind up not waking up due to race conditions, because two senders notify_one, and only one person wakes up. notify is (generally) implemented such that it wakes the waiter after you drop the lock, so you don't have to worry about someone waking up while the lock is still held.
    For people still confused, be aware that condvar is a concept decades old, with lots of questions answered online independent of Rust.
    Assigning to _ drops temporaries. But the tx variable is still holding onto the reference.

    • @jonhoo
      @jonhoo  4 года назад +8

      There seems to be "hot" debate on this topic. The man page for pthread_cond_broadcast has this to say: "The pthread_cond_broadcast() or pthread_cond_signal() functions may be called by a thread whether or not it currently owns the mutex that threads calling pthread_cond_wait() or pthread_cond_timedwait() have associated with the condition variable during their waits; however, if predictable scheduling behavior is required, then that mutex shall be locked by the thread calling pthread_cond_broadcast() or pthread_cond_signal()." This suggests that either way is fine. There are also posts out there suggesting that unlocking first measurably decreases contention: stackoverflow.com/questions/17101922/do-i-have-to-acquire-lock-before-calling-condition-variable-notify-one

  • @devajitasem4618
    @devajitasem4618 4 года назад +42

    Nom nom nom...

  • @xiuxiu624
    @xiuxiu624 3 года назад +4

    Damn I just found your channel - your videos have been extremely helpful. Thank you

  • @markday3145
    @markday3145 4 года назад +4

    Whoa. That “None if inner.senders == 0 =>” condition in the match looks weird. I’m going to have to go back and reread that section of The Book. That’s why I like these streams. I tend to learn new things that are incidental to the main topic.

    • @jonhoo
      @jonhoo  4 года назад +10

      That's one of my primary hopes with them - a sort of "learning by osmosis" by observing someone relatively experienced write "real" code :) Glad that it seems to be working!

    • @alvarozamora2679
      @alvarozamora2679 2 года назад

      @@jonhoo indeed it is!

  • @dantenotavailable
    @dantenotavailable 4 года назад +6

    ... ok i haven't watched the video yet but i just had to comment. Love the intro!

  • @sivakrishna4270
    @sivakrishna4270 Год назад

    Thanks Jon, this series is proving to be really helpful along with those Q&A during the stream. Really appreciate your work!

  • @Blure
    @Blure 4 года назад +4

    Hello Jon, The Crust of Rust series has been incredibly handy thus far. Thanks!
    In other hand, and this is quite off topic but, what vim colorscheme are you using? It looks darker than base16-gruvbox-dark-hard.

    • @jonhoo
      @jonhoo  4 года назад +4

      Ah, that's just because of the compression the live stream is using. That'll hopefully be better in the next stream (or if you look at some older ones). It really is the dark hard version of gruvbox :)

  • @Mandragore12345
    @Mandragore12345 3 года назад +1

    In the video you didn't end up using strong_count from Arc, because you wouldn't know if the other clone of the Arc was a sender or a receiver. Wouldn't it be ok to notify_one anyway? If there is a receiver remaining all is ok. If there is no receiver remaining, there is no one waiting on the condvar, and thus nothing happens.
    Maybe it's because a call to notify_one is expensive? But then this would be a very rare event, and the trade off is a somewhat simplified implementation. Thanks for the videos!

  • @simply.matias
    @simply.matias 12 дней назад

    Great insights, thanks!

  • @RitobanRoyChowdhury
    @RitobanRoyChowdhury 4 года назад +6

    Great Video!!
    But please setup Github Dark mode, there's a bunch of extensions for it, or even just a CSS file loaded with Stylo/Stylish would help immensely!

    • @jonhoo
      @jonhoo  4 года назад +10

      I actually personally don't like dark mode for web pages. I only have it set up for the docs on stream because I know some people watch the streams in dark rooms :) I very rarely go on GitHub during a stream, so don't think it's quite worth it to have an extension (that I'd also want to disable otherwise) just for the streams. I do try to warn in the rare cases where I'm about to switch to a bright screen though!

  • @advertslaxxor
    @advertslaxxor 4 года назад +2

    Sorry to hear you're moving to L.A.
    Best of luck, you will be missed :(

    • @jonhoo
      @jonhoo  4 года назад +14

      Why sorry? I'll still be making more videos from there!

  • @DrOptix
    @DrOptix 2 года назад

    Hello, first of all this is a great channel. There are places for 10mins videos and there are places for > 1H videos.
    Now I'm in a place where I want to go deeper on some topics.
    Now, I guess you are on a linux flavor. What are you using to record the screen? Also are you using a wayland based shell. I try to use OBS on a KDE wayland shell and all I get is a beautiful black screen. Any tips would be great!
    Thank you!

    • @jonhoo
      @jonhoo  2 года назад

      Nope, this is good old X with OBS. I do want to try to move on over to Wayland soon though!

  • @fernandoherrera2769
    @fernandoherrera2769 3 года назад +1

    Hi Jon. Thanks a lot for these videos. They have been very helpful while learning Rust. I have been studying this code you wrote for channels and I was wondering what would be the best way to handle the error you get from locking the mutex. It seems everybody recommends to just unwrap it and let it panic. Is that the best we can do?

    • @jonhoo
      @jonhoo  3 года назад +4

      That's a good question! I suggest you go take a look at blog.rust-lang.org/2020/12/11/lock-poisoning-survey.html :)

  • @aresli7058
    @aresli7058 10 месяцев назад

    Thanks Jon, but I have a question about condvar. At last, the condvar is not in the mutex, so I think multiple threads can call condvar.notify_one at the same time. Will that causes an race?

  • @michaeleaster1815
    @michaeleaster1815 4 года назад

    Terrific video: thank you. I didn't think I'd watch the entire video, but it was quite interesting!

  • @semigsedem
    @semigsedem 2 года назад

    I was stuck on only concidering recv() and try_recv() methods for both waiting until a 'send' and occasionally checking for R-user interrupts. You mentioned a implementation could have the reciever awoken by a sender or for any other signal such as a time out. And simple enough flume and mspc have the recv_timeout() method to do that all along.

  • @amaraojiji
    @amaraojiji 2 года назад

    I have a very odd request: can you use non-standard mouse pointer for your streams? Your pointer is exactly like default pointer in Cinnamon (and others DE), and it causes second pointer to be in the video, which is a bit confusing...

  • @Zizaco
    @Zizaco 4 года назад

    The video/stream was very helpful to understand channels. thanks

  • @RuslanKovtun
    @RuslanKovtun 2 года назад

    54:40 most of the time you want any additional information available, similar to `Result` vs `-1`.

  • @rnavarro50
    @rnavarro50 3 года назад +1

    Does a data structure that broadcasts every send to every receiver could be considered a "channel flavor" too? Or is this a totally different concept?

  • @foobargorch
    @foobargorch 3 года назад

    fwiw Go doesn't have unbounded channels, but that's trivially implementable using two rendezvous or bounded channels and a goroutine that buffers items between two branches of a select loop, that's equivalent.

  • @Simon-xi8tb
    @Simon-xi8tb 4 года назад +4

    Channels are just meeting points between two threads. I have some experience with CSP via Clojure. Are semantics in Rust the same as in core.async ? Are things like alt, sliding buffers, dropping buffers implemented ?

  • @PandaNuker
    @PandaNuker Год назад +1

    doesn't the memswap optimisation invalidate the FIFO assumption?

  • @cutyboi8630
    @cutyboi8630 4 года назад +1

    We need Ferris in intro too 😁

  • @anonymousnyancat3231
    @anonymousnyancat3231 4 года назад

    Are your dotfiles available?
    I love the Firefox theme and (poly?)bar. (also shell, neovim conf and whatnot ;))

    • @jonhoo
      @jonhoo  4 года назад +1

      They are! github.com/jonhoo/configs :)

    • @anonymousnyancat3231
      @anonymousnyancat3231 4 года назад

      @@jonhoo Thanks a ton! And also for all the wonderful Rust videos. You've really helped me learn a lot. (P.s. is there a way to suggest videos and not just vote on them? I'd love to see a clean Brainfuck interpreter written in Rust. (The existing implementations (that I found, at least) and my own are all a bit shabby with structure, so I'd love to see you create one.))

    • @jonhoo
      @jonhoo  4 года назад

      Thank you! There isn't a formal process, no; sending it my way as a suggestions is the best way 😅

  • @TheLANBeforeTime-uo9ph
    @TheLANBeforeTime-uo9ph 6 месяцев назад

    A side question for Nvim: on 24:04, Jon quickly duplicated the current paragraph/function, how did he do it?

    • @WatchingScience-gv8pe
      @WatchingScience-gv8pe 4 месяца назад

      Probably visual inner paragraph yank -> vipy.
      Could also be yank inner paragraph with the flash setting on (that shows which section you've copied)

    • @TheLANBeforeTime-uo9ph
      @TheLANBeforeTime-uo9ph 4 месяца назад

      The mysterious part is not the yank but the paste without the cursor moved. I think your answer couldn’t do it like so, can it?

    • @WatchingScience-gv8pe
      @WatchingScience-gv8pe 4 месяца назад

      Both options should do it without moving the Cursor imho

  • @_alyssarose
    @_alyssarose 4 года назад

    Is deduplicating the data for a double buffered stream feasible? PS Love your videos, they inspired me to start coding in Rust!

    • @jonhoo
      @jonhoo  4 года назад

      Well, there's no actual double buffering here. When I say it uses "twice the memory", it's really just that it has twice the reserved memory for the capacity of the VecDeques. It doesn't actually duplicate the sent data, like strings or vectors.
      So happy to hear that, thank you! :D

    • @_alyssarose
      @_alyssarose 4 года назад

      @@jonhoo okay I misunderstood then. So the while the memory footprint grows to accommodate the second VecDeque the data is still stored at most once and is just there to allow for the receiver to avoid locking if there's data in the second queue?

    • @jonhoo
      @jonhoo  4 года назад

      Exactly!

  • @stephenjames2951
    @stephenjames2951 3 года назад

    Should the Clone be protected by the mutex? Or does Arc protect itself.

  • @evanxg852000
    @evanxg852000 3 года назад

    0:32:55 But you said previously that the thread can be waken up by the os for no valid reason. In that case, are you still handled a LockGuard?
    lets say TA is holding the Convar lock while TB is waiting; and for some reason the OS wakes up TB while TA is not done.
    Can the OS let this happen? Is the Guard given back as Poisoned ? my concern is if the wait always return the Guard while not guaranteeing the other is done then there could be issues.

    • @jonhoo
      @jonhoo  3 года назад +1

      Ah, this is implemented internally in the Condvar in Rust. If it gets a spurious wake-up, and then fails to get the lock, it won't be able to produce a `LockGuard` to return, and therefore will instead go back to sleep.

  • @avjewe
    @avjewe 3 года назад

    What do you recommend for my usual use case : single sender (adding work units) multiple receivers (doing the work)?

    • @semigsedem
      @semigsedem 2 года назад

      Noob here, but a Arc might do the trick. T is a job, and any thread is free to push or pop jobs. Only idling threads are contending for the Mutex. For something both easy and elegant likely rayon is good starting point.

  • @jaspervisser181
    @jaspervisser181 4 года назад

    What was the open discussion about _ will not drop the value, mentioned around 51:12?

    • @jonhoo
      @jonhoo  4 года назад +1

      Take a look at twitter.com/jonhoo/status/1292103918198104064 :)

    • @jaspervisser181
      @jaspervisser181 4 года назад

      @@jonhoo Thanks! Great video btw :)

  • @clubhi
    @clubhi 3 года назад

    Why is it that not taking a lock as many times means that it will be able to take locks faster. Is the os penalizing threads that change state frequently?

    • @jonhoo
      @jonhoo  3 года назад

      Every time the CPU tries to take a lock, it needs to coordinate with any other CPUs that are _also_ trying to take the lock, or at the very least with the CPU that previously held the lock. If CPUs are trying to acquire the lock less frequently, that means that there are both fewer cores to coordinate with, and it is more likely that _this_ CPU is the last one to have held the lock (and therefore coordination is unnecessary). If you're curious about what happens under the hood, I recommend reading about MESI: en.wikipedia.org/wiki/MESI_protocol

  •  8 месяцев назад

    When there are no more senders (dropped) documentation says the receivers will return an Err.

  • @efraimdeluxe
    @efraimdeluxe 4 года назад

    Nice Intro!

  • @lucaspelegrino1
    @lucaspelegrino1 4 года назад +1

    What is "high contention" and "low contention"?

    • @jackmccarthy7644
      @jackmccarthy7644 3 года назад +2

      Contention refers to how often multiple threads are trying to access the same data. If a program has high contention, then lots of threads are trying to read/write to the same place at the same time, and will likely result in a lot of blocking, waiting, and fighting for mutex locks. Low contention means that there's usually only one thread trying to read/write at a time, so there will be much less blocking.

  • @raptazure868
    @raptazure868 4 года назад

    Thanks a lot 😋

  • @sheikhshakilakhtar6844
    @sheikhshakilakhtar6844 4 года назад

    Sorry, but I have two irrelevant questions which I would like you to answer.
    1. Is your window manager i3?
    2. Why are you using fish as opposed to bash/zsh?

    • @jonhoo
      @jonhoo  4 года назад +1

      Take a look at my video about my desktop setup over at ruclips.net/video/ycMiMDHopNc/видео.html :)
      These days, I use bspwm, not xmonad, as my window manager.

    • @sheikhshakilakhtar6844
      @sheikhshakilakhtar6844 4 года назад

      @@jonhoo Thanks a lot, Sir. One more question, if you do not mind. I am a beginner programmer learning C. Can you suggest projects/problems in C which can help me develop my programming skills in C?

    • @jonhoo
      @jonhoo  4 года назад +1

      I can't say I have much to recommend in the space of C education. I'd recommend you start with a different language, and then work your way up to C :) If you are intent on pursuing C, then I'd suggest starting with something like Project Euler, which has fairly well-defined and isolated exercises you can get started with.

  • @simonfarre4907
    @simonfarre4907 3 года назад

    Interesting that "let _ = ..." doesn't drop. That doesn't seem to be the case for _anything_ (even when it's scoped, which is even more weird) so I wonder what let _ = ... actually gets compiled to? However, if you would have scoped it, and named the variable, something like what I've written down below, it would have worked:
    #[test]
    fn close() {
    let (tx, rx) = channel::();
    {
    let a = tx;
    }
    assert_eq!(rx.recv(), None);
    }
    So this is strange. So "let _ = ..." doesn't actually seem to do anything when just doing it to another variable.

    • @megumin4625
      @megumin4625 2 года назад

      `let _` is a no-op. It gets compiled to nothing at all (no assembly). What it's good for is intentionally ignoring compiler warnings like `Result not used`.

    • @simonfarre4907
      @simonfarre4907 2 года назад +1

      @@megumin4625 I can't remember where in the video this was in response to, but yeah it is a wild card, but it wasn't what my comment was about, if I remember correctly, I think it was about a compiler error given somewhere in the video.
      Ah yes, he tried to force a drop, by using "let _ = ..." but, right, assigning _ to a value is a no op, which can be a bit confusing, as this can have "different" behavior than if assigned to a return from a function.
      It is at 52:30

    • @megumin4625
      @megumin4625 2 года назад +1

      @@simonfarre4907 I've tested this in godbolt, and `let _` does nothing to the assembly even in return. It drops in place if it was going to already, even without `let _`.
      I suspect this point might have gotten confused because people sometimes saw drops happening there, but without realizing it does it regardless (because it's a no-op in the first place).
      I saw a post explaining that `let _ = {i};` causes a drop, but `{i};` does the exact same thing in the assembly even
      (If anyone has an example to prove me wrong, I'd love to see it; I've been reading the assembly and cannot yet find that it's not a no-op)

  • @aliakbarmostafaei
    @aliakbarmostafaei Месяц назад

    This isn't available in HD or something wrong with my RUclips?!

    • @jonhoo
      @jonhoo  Месяц назад +1

      It should be, so that may then be a problem on your end.

    • @aliakbarmostafaei
      @aliakbarmostafaei Месяц назад

      @@jonhoo It was, HD is available on my desktop browser. Thank you for the quality Rust content!

  • @BboyKeny
    @BboyKeny Год назад

    I needed to use channels to send a closure to JavaScript with wasm

  • @TomasSandven
    @TomasSandven 2 года назад

    Can you fork and use channels to communicate between processes? If so, does T need to be Send?

  • @yourordinaryme
    @yourordinaryme 3 года назад

    AHHHH for the love of christ if you use Vim use find/replace or better yet a rename symbol plugin for changing names haha

  • @PaulSebastianM
    @PaulSebastianM 4 года назад

    Panama... Ouch! XD

  • @RoamingAdhocrat
    @RoamingAdhocrat Год назад

    let inner = stuff;
    let inner = Arc::new(inner);
    is this idiomatic Rust, to create a variable and immediately replace it?
    can you not write:
    let inner = Arc::new(stuff);
    which I can see results in deeper nesting & therefore not great

  • @driziiD
    @driziiD 3 года назад

    mutex + condvar = monitor