Crust of Rust: Channels

แชร์
ฝัง
  • เผยแพร่เมื่อ 20 พ.ย. 2024

ความคิดเห็น • 86

  • @megumin4625
    @megumin4625 2 ปีที่แล้ว +20

    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 ปีที่แล้ว +52

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

  • @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!

  • @simonfarre4907
    @simonfarre4907 3 ปีที่แล้ว +11

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

  • @nicolaswolyniec1354
    @nicolaswolyniec1354 10 หลายเดือนก่อน +1

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

  • @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.

  • @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

  • @jasonleo
    @jasonleo 4 ปีที่แล้ว +43

    Haha, new intro

  • @devajitasem4618
    @devajitasem4618 4 ปีที่แล้ว +42

    Nom nom nom...

  • @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!

  • @xiuxiu624
    @xiuxiu624 3 ปีที่แล้ว +4

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

  • @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!

  • @dantenotavailable
    @dantenotavailable 4 ปีที่แล้ว +6

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

  • @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.

  • @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 :)

  • @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 ?

  • @michaeleaster1815
    @michaeleaster1815 4 ปีที่แล้ว

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

  • @sivakrishna4270
    @sivakrishna4270 ปีที่แล้ว

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

  • @RuslanKovtun
    @RuslanKovtun 2 ปีที่แล้ว

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

  • @simply.matias
    @simply.matias หลายเดือนก่อน

    Great insights, thanks!

  • @Zizaco
    @Zizaco 4 ปีที่แล้ว

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

  • @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.

  • @cutyboi8630
    @cutyboi8630 4 ปีที่แล้ว +1

    We need Ferris in intro too 😁

  • @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 :)

  • @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!

  • @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!

  • @rnavarro50
    @rnavarro50 4 ปีที่แล้ว +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?

  • @aresli7058
    @aresli7058 11 หลายเดือนก่อน

    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?

  • @PandaNuker
    @PandaNuker ปีที่แล้ว +1

    doesn't the memswap optimisation invalidate the FIFO assumption?

  • @TheLANBeforeTime-uo9ph
    @TheLANBeforeTime-uo9ph 7 หลายเดือนก่อน

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

    • @WatchingScience-gv8pe
      @WatchingScience-gv8pe 5 หลายเดือนก่อน

      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 5 หลายเดือนก่อน

      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 5 หลายเดือนก่อน

      Both options should do it without moving the Cursor imho

  •  9 หลายเดือนก่อน

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

  • @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...

  • @stephenjames2951
    @stephenjames2951 3 ปีที่แล้ว

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

  • @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 :)

  • @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.

  • @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.

  • @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 😅

  • @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!

  • @lucaspelegrino1
    @lucaspelegrino1 4 ปีที่แล้ว +1

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

    • @jackmccarthy7644
      @jackmccarthy7644 4 ปีที่แล้ว +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.

  • @clubhi
    @clubhi 4 ปีที่แล้ว

    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  4 ปีที่แล้ว

      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

  • @efraimdeluxe
    @efraimdeluxe 4 ปีที่แล้ว

    Nice Intro!

  • @BboyKeny
    @BboyKeny 2 ปีที่แล้ว

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

  • @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)

  • @raptazure868
    @raptazure868 4 ปีที่แล้ว

    Thanks a lot 😋

  • @_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!

  • @aliakbarmostafaei
    @aliakbarmostafaei 2 หลายเดือนก่อน

    This isn't available in HD or something wrong with my TH-cam?!

    • @jonhoo
      @jonhoo  2 หลายเดือนก่อน +1

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

    • @aliakbarmostafaei
      @aliakbarmostafaei 2 หลายเดือนก่อน

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

  • @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 th-cam.com/video/ycMiMDHopNc/w-d-xo.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.

  • @TomasSandven
    @TomasSandven 2 ปีที่แล้ว

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

  • @driziiD
    @driziiD 3 ปีที่แล้ว

    mutex + condvar = monitor

  • @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

  • @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