1 00:00:06,600 --> 00:00:09,060 - Imagine the scenario where multiple threads 2 00:00:09,060 --> 00:00:11,220 need to access the same data. 3 00:00:11,220 --> 00:00:14,370 So, here's a piece of data. 4 00:00:14,370 --> 00:00:17,010 Thread one wants to access the data 5 00:00:17,010 --> 00:00:20,700 and thread two wants to access the same data. 6 00:00:20,700 --> 00:00:22,710 This is potentially dangerous. 7 00:00:22,710 --> 00:00:25,110 One thread might be reading the data 8 00:00:25,110 --> 00:00:26,550 while another thread is updating it. 9 00:00:26,550 --> 00:00:28,890 So you can get like a race condition 10 00:00:28,890 --> 00:00:31,230 and you can do this in Rust, 11 00:00:31,230 --> 00:00:33,360 but then you have to use Mutexes. 12 00:00:33,360 --> 00:00:34,920 There's a class of structure, 13 00:00:34,920 --> 00:00:37,740 I should say called Mutex in Rust, 14 00:00:37,740 --> 00:00:41,520 where you can, one thread can lock a piece of data 15 00:00:41,520 --> 00:00:44,490 and another thread would then block 16 00:00:44,490 --> 00:00:46,060 until the Mutex is released 17 00:00:46,950 --> 00:00:49,770 and then the other thread can access, okay? 18 00:00:49,770 --> 00:00:52,710 So it is possible to kind of simultaneously 19 00:00:52,710 --> 00:00:54,690 access the same data, but it's quite tricky. 20 00:00:54,690 --> 00:00:58,860 The preferred way is to use something called a channel. 21 00:00:58,860 --> 00:01:01,860 A channel is like a pipeline between threads. 22 00:01:01,860 --> 00:01:04,260 One thread can send data into the channel 23 00:01:04,260 --> 00:01:05,670 and another thread can read data 24 00:01:05,670 --> 00:01:07,470 from the channel without contention. 25 00:01:07,470 --> 00:01:10,020 So it is very much like a pipeline 26 00:01:10,020 --> 00:01:12,780 where one thread sends data 27 00:01:12,780 --> 00:01:16,740 or transmits data into the channel 28 00:01:16,740 --> 00:01:20,790 and another thread receives the data 29 00:01:20,790 --> 00:01:22,200 from that channel, okay. 30 00:01:22,200 --> 00:01:24,483 So it's like message queuing in memory. 31 00:01:25,680 --> 00:01:29,700 So this channel that I've drawn here, 32 00:01:29,700 --> 00:01:32,459 in order to create this channel, this kind of conduit, 33 00:01:32,459 --> 00:01:37,080 there's a module called MPSE, 34 00:01:37,080 --> 00:01:40,320 multiple producer single consumer. 35 00:01:40,320 --> 00:01:41,940 That's what that stands for. 36 00:01:41,940 --> 00:01:46,800 And in the multiple producer single consumer module, 37 00:01:46,800 --> 00:01:49,410 easy for you to say, there's a channel function, 38 00:01:49,410 --> 00:01:50,997 and it creates a channel, 39 00:01:50,997 --> 00:01:53,550 and it actually gives you back a tuple. 40 00:01:53,550 --> 00:01:55,740 The channel function returns the tuple 41 00:01:55,740 --> 00:01:57,333 containing two objects. 42 00:01:58,320 --> 00:02:01,120 It gives you back a transmitter object 43 00:02:02,430 --> 00:02:06,390 which you can use to transmit data into the channel, 44 00:02:06,390 --> 00:02:08,610 and also gives you a receiver object 45 00:02:08,610 --> 00:02:10,950 which you can use to receive data 46 00:02:10,950 --> 00:02:12,960 from the channel like that, okay? 47 00:02:12,960 --> 00:02:14,850 So the channel function returns a tuple. 48 00:02:14,850 --> 00:02:19,320 You can use the TX object to send data in to transmit data 49 00:02:19,320 --> 00:02:22,740 and you can use the RX object to receive data 50 00:02:22,740 --> 00:02:24,300 at the other side. 51 00:02:24,300 --> 00:02:28,290 So that's quite a straightforward protocol really. 52 00:02:28,290 --> 00:02:30,120 So channel returns a tuple. 53 00:02:30,120 --> 00:02:32,640 TX is the transmitter object 54 00:02:32,640 --> 00:02:34,803 and RX is the receiver object. 55 00:02:35,910 --> 00:02:40,503 So you can receive a, you can send a single message 56 00:02:40,503 --> 00:02:43,126 to a channel like this. 57 00:02:43,126 --> 00:02:46,470 On the previous slide, we'd created the channel 58 00:02:46,470 --> 00:02:48,840 and we got back a TX object. 59 00:02:48,840 --> 00:02:50,580 So you can use TX dot send. 60 00:02:50,580 --> 00:02:53,030 You basically sending a message into the channel. 61 00:02:54,150 --> 00:02:55,950 I've chosen to send a string here. 62 00:02:55,950 --> 00:02:56,790 Hei hei. 63 00:02:56,790 --> 00:02:59,508 That's Norwegian for "Hello". 64 00:02:59,508 --> 00:03:01,590 When you call the send function, 65 00:03:01,590 --> 00:03:03,120 like a lot of functions in the A P I, 66 00:03:03,120 --> 00:03:05,310 it returns a result enum, 67 00:03:05,310 --> 00:03:06,780 and the result enum can indicate 68 00:03:06,780 --> 00:03:09,420 whether the message has been sent successfully 69 00:03:09,420 --> 00:03:10,890 or whether an error occurred. 70 00:03:10,890 --> 00:03:13,890 So TX dot send returns a result, 71 00:03:13,890 --> 00:03:16,410 which can be either okay or an error. 72 00:03:16,410 --> 00:03:17,610 I'm assuming it's gonna work. 73 00:03:17,610 --> 00:03:19,440 So I just call unwrap. 74 00:03:19,440 --> 00:03:21,690 Okay? So that's assuming that the message 75 00:03:21,690 --> 00:03:23,970 was sent successfully into the channel. 76 00:03:23,970 --> 00:03:26,610 So this thread I've just shown you 77 00:03:26,610 --> 00:03:28,900 will have used the transmitter object 78 00:03:29,850 --> 00:03:33,300 to send a message into the channel, like so. 79 00:03:33,300 --> 00:03:35,280 The main thread can then receive the message 80 00:03:35,280 --> 00:03:37,350 from the channel like this. 81 00:03:37,350 --> 00:03:41,480 The main thread, RX receive, the receive function, 82 00:03:41,480 --> 00:03:44,670 will basically give us back the message afterwards. 83 00:03:44,670 --> 00:03:48,510 And again, the receive function returns a result 84 00:03:48,510 --> 00:03:50,010 and a result enum, 85 00:03:50,010 --> 00:03:53,700 which indicates either an okay result or error. 86 00:03:53,700 --> 00:03:54,990 I call the unwrap function. 87 00:03:54,990 --> 00:03:57,090 I'm expecting this to work, okay? 88 00:03:57,090 --> 00:03:59,250 If I was gonna be more tentative 89 00:03:59,250 --> 00:04:01,110 then when I call the receive function 90 00:04:01,110 --> 00:04:02,460 and I get back a result, 91 00:04:02,460 --> 00:04:03,660 I'd use a match statement. 92 00:04:03,660 --> 00:04:06,420 Match, okay, match error. 93 00:04:06,420 --> 00:04:08,640 In this simple example, I'm gonna assume it's gonna work. 94 00:04:08,640 --> 00:04:09,930 So I call the unwrap function 95 00:04:09,930 --> 00:04:12,600 and it'll give you the actual value that was transmitted. 96 00:04:12,600 --> 00:04:15,480 So up here I transmitted hei, hei. 97 00:04:15,480 --> 00:04:17,926 That would be the value that I should receive 98 00:04:17,926 --> 00:04:19,650 back on the main thread. 99 00:04:19,650 --> 00:04:20,790 Alright? So it's a very simple 100 00:04:20,790 --> 00:04:25,140 send from one thread, receive from another. 101 00:04:25,140 --> 00:04:27,060 Let's actually run an example. 102 00:04:27,060 --> 00:04:30,120 So the usual project, we'll have a look at main 103 00:04:30,120 --> 00:04:32,340 and then we'll have a look at the demo channels 104 00:04:32,340 --> 00:04:34,290 with a single message. 105 00:04:34,290 --> 00:04:36,480 In the demo that's coming up next, 106 00:04:36,480 --> 00:04:38,700 we're going to see how to send multiple messages. 107 00:04:38,700 --> 00:04:39,993 Okay? So that's to come. 108 00:04:41,310 --> 00:04:42,810 Let's take a look at the code. 109 00:04:43,830 --> 00:04:46,800 Right? So, well, I guess I need to first of all, 110 00:04:46,800 --> 00:04:49,680 uncomment the relevant bit of my demo. 111 00:04:49,680 --> 00:04:52,173 Demo channels for a single message. 112 00:04:53,340 --> 00:04:55,950 And here is the code. 113 00:04:55,950 --> 00:05:00,950 So I, first of all notice that I've imported M P S E, 114 00:05:00,960 --> 00:05:03,420 multiple producer single consumer, 115 00:05:03,420 --> 00:05:04,770 created a channel, 116 00:05:04,770 --> 00:05:05,940 gives me back a tuple, 117 00:05:05,940 --> 00:05:07,620 it gives you back a transmitter object 118 00:05:07,620 --> 00:05:09,810 that I can use to send messages 119 00:05:09,810 --> 00:05:12,560 and the receiver object, I can use to receive messages. 120 00:05:13,710 --> 00:05:14,543 Right? 121 00:05:14,543 --> 00:05:17,490 So in my thread here, 122 00:05:17,490 --> 00:05:21,730 I use the transmitter to send a message, hei, hei 123 00:05:22,830 --> 00:05:24,419 and then unwrap the result. 124 00:05:24,419 --> 00:05:27,903 While I'm here, notice the 'move' keyword again. 125 00:05:28,749 --> 00:05:32,970 It's important that this object is owned by the thread. 126 00:05:32,970 --> 00:05:36,000 Okay? So we have to, that object there has to be owned, 127 00:05:36,000 --> 00:05:38,820 moved into the thread, like so. 128 00:05:38,820 --> 00:05:41,820 So the channel now contains the message hei, hei. 129 00:05:41,820 --> 00:05:43,806 The main thread down here, 130 00:05:43,806 --> 00:05:47,250 using the receiver object that was returned, 131 00:05:47,250 --> 00:05:50,340 basically my handle onto the channel, 132 00:05:50,340 --> 00:05:51,690 using the receiver object, 133 00:05:51,690 --> 00:05:55,470 I can call the receive method that returns a result, 134 00:05:55,470 --> 00:05:57,030 okay or error. 135 00:05:57,030 --> 00:05:58,080 Let's hope it works. 136 00:05:58,080 --> 00:06:00,570 Let's unwrap it to get back the actual string. 137 00:06:00,570 --> 00:06:01,710 Hei, hei. 138 00:06:01,710 --> 00:06:04,560 And then I can say I've received hei, hei. 139 00:06:04,560 --> 00:06:07,170 and we'll wait for, it's always courteous, 140 00:06:07,170 --> 00:06:08,910 if you've kicked off another thread, 141 00:06:08,910 --> 00:06:11,310 it's always courteous to wait for that thread to finish 142 00:06:11,310 --> 00:06:15,210 before you terminate, just in case there's a timing issue. 143 00:06:15,210 --> 00:06:16,380 So I think that should work fine. 144 00:06:16,380 --> 00:06:17,430 Let's run it and see. 145 00:06:23,193 --> 00:06:24,090 Okay then. 146 00:06:24,090 --> 00:06:28,470 So here's my demo in demo channels, single message. 147 00:06:28,470 --> 00:06:30,810 And I sent the message there. 148 00:06:30,810 --> 00:06:31,920 I received the message. 149 00:06:31,920 --> 00:06:36,300 Received hei, hei, so very straightforward A P I, 150 00:06:36,300 --> 00:06:38,820 which is nice, simple is good. 151 00:06:38,820 --> 00:06:39,900 Right, so what we're gonna look at now 152 00:06:39,900 --> 00:06:42,660 is how to send and receive multiple messages. 153 00:06:42,660 --> 00:06:45,510 So I've got a slightly different example now 154 00:06:45,510 --> 00:06:48,210 where I'm going to spawn a thread, 155 00:06:48,210 --> 00:06:53,210 which is going to send 10 messages into the channel. 156 00:06:53,940 --> 00:06:57,200 So the channel, it really is like a queue. 157 00:06:57,200 --> 00:06:59,710 You can send as many messages as you want 158 00:07:00,810 --> 00:07:04,890 into the channel like that, okay? 159 00:07:04,890 --> 00:07:06,060 And that's what I've done. 160 00:07:06,060 --> 00:07:09,183 I've sent, I've got a string here. 161 00:07:10,410 --> 00:07:13,893 It'll say message one, 162 00:07:14,760 --> 00:07:15,810 it's gonna loop on 10 times, 163 00:07:15,810 --> 00:07:19,500 and then it'll say message two, message three, message four. 164 00:07:19,500 --> 00:07:22,800 So each string will be sent, it'll be message one, 165 00:07:22,800 --> 00:07:24,633 message two, message three, 166 00:07:25,800 --> 00:07:27,570 and eventually message 10. 167 00:07:27,570 --> 00:07:29,010 So those are the messages are gonna be 168 00:07:29,010 --> 00:07:31,080 in queued in the channel. 169 00:07:31,080 --> 00:07:33,330 And then to receive them, just write the loop. 170 00:07:33,330 --> 00:07:36,240 You can iterate over the receiver, okay? 171 00:07:36,240 --> 00:07:37,710 This is a pattern that you see quite a lot 172 00:07:37,710 --> 00:07:39,300 in other languages like Python. 173 00:07:39,300 --> 00:07:41,070 Every time you iterate, it consumes. 174 00:07:41,070 --> 00:07:43,650 So when you iterate over the receiver 175 00:07:43,650 --> 00:07:47,100 it basically calls the receive function on this then. 176 00:07:47,100 --> 00:07:49,577 Waiting for the next value to return. 177 00:07:49,577 --> 00:07:51,840 This would be the value that gets returned. 178 00:07:51,840 --> 00:07:54,630 Okay? So it'd be like message one will be returned 179 00:07:54,630 --> 00:07:57,183 and then message two and then message three. 180 00:07:58,050 --> 00:08:01,410 Okay? So have a loop to send multiple messages 181 00:08:01,410 --> 00:08:04,338 and then have a loop to receive multiple messages as well. 182 00:08:04,338 --> 00:08:06,000 Quite straightforward. 183 00:08:06,000 --> 00:08:07,950 You might have actually guessed this, 184 00:08:07,950 --> 00:08:11,430 if you had a inkling and it kind of makes sense. 185 00:08:11,430 --> 00:08:12,900 So we'll run the demo for this as well. 186 00:08:12,900 --> 00:08:15,870 Same project, same main file, but a slightly 187 00:08:15,870 --> 00:08:18,990 different demo to allow us to send multiple messages 188 00:08:18,990 --> 00:08:21,333 and to receive multiple messages as well. 189 00:08:22,230 --> 00:08:25,510 Okay? So back in our code in main 190 00:08:27,167 --> 00:08:30,510 let's comment that one out and let's uncomment this one. 191 00:08:30,510 --> 00:08:33,000 Demo channels, multiple messages. 192 00:08:33,000 --> 00:08:34,590 Quite exciting. 193 00:08:34,590 --> 00:08:35,643 And here it is. 194 00:08:36,480 --> 00:08:38,790 So create a channel, 195 00:08:38,790 --> 00:08:41,940 get back a transmitter object and a receiver object. 196 00:08:41,940 --> 00:08:46,890 In my background thread, 10 times, send a message. 197 00:08:46,890 --> 00:08:48,720 Oh, I've got a delay as well, 198 00:08:48,720 --> 00:08:51,780 just to make it so it isn't in, it isn't all instantaneous. 199 00:08:51,780 --> 00:08:52,860 It's gonna delay. 200 00:08:52,860 --> 00:08:55,500 And then send another message and then a one second delay. 201 00:08:55,500 --> 00:08:57,360 And then it'll send the next message. 202 00:08:57,360 --> 00:09:00,210 Okay? So as I send a message from one thread, 203 00:09:00,210 --> 00:09:02,160 they're gonna be received from the other thread, 204 00:09:02,160 --> 00:09:05,040 on the receiving side, it'll be receiving the messages, 205 00:09:05,040 --> 00:09:07,170 it'll iterate over this receiver object. 206 00:09:07,170 --> 00:09:10,230 Remember the receiver object you get back from the channel? 207 00:09:10,230 --> 00:09:12,039 You can iterate over that, which basically means 208 00:09:12,039 --> 00:09:15,300 wait for the next one until it's empty. 209 00:09:15,300 --> 00:09:17,763 And then we, we terminate the application. 210 00:09:18,743 --> 00:09:23,310 So this is going to work, 211 00:09:23,310 --> 00:09:24,143 let's hope so. 212 00:09:27,298 --> 00:09:30,180 There we are, so the messages that were sent 213 00:09:30,180 --> 00:09:32,403 are being received over one second interval. 214 00:09:33,930 --> 00:09:36,810 I'm actually gonna put a print statement 215 00:09:36,810 --> 00:09:38,823 to say that I'm sending a message. 216 00:09:39,690 --> 00:09:41,553 So I think here, 217 00:09:42,840 --> 00:09:44,943 println, send in, 218 00:09:46,650 --> 00:09:49,260 and then the S, "S" is the message we're sending, 219 00:09:49,260 --> 00:09:53,580 like message one, that's the string that I'm going to, 220 00:09:53,580 --> 00:09:54,750 I'm gonna echo it on the screen 221 00:09:54,750 --> 00:09:56,850 so I can see when the message is sent 222 00:09:56,850 --> 00:09:58,920 and when it's received to see how the sending 223 00:09:58,920 --> 00:10:01,570 and the receiving kind of interleave with each other. 224 00:10:02,670 --> 00:10:05,463 I feel I'm gonna need more screen space. 225 00:10:07,740 --> 00:10:08,913 Okay, then let's do it. 226 00:10:12,750 --> 00:10:17,070 So a message gets sent and received, sent and received. 227 00:10:17,070 --> 00:10:18,780 So it's completely in sync. 228 00:10:18,780 --> 00:10:21,000 One thread is sending a message 229 00:10:21,000 --> 00:10:22,650 and the other thread receives it immediately. 230 00:10:22,650 --> 00:10:24,060 So they are interleaved. 231 00:10:24,060 --> 00:10:26,160 It's not like we send all the messages 232 00:10:26,160 --> 00:10:27,540 and then it receives 'em afterwards. 233 00:10:27,540 --> 00:10:29,250 They are working concurrently, 234 00:10:29,250 --> 00:10:32,070 sending and receiving at the same time. 235 00:10:32,070 --> 00:10:34,380 So that wraps up this lesson. 236 00:10:34,380 --> 00:10:36,270 We've seen how to create threads. 237 00:10:36,270 --> 00:10:38,430 We've seen how to wait for threads to finish. 238 00:10:38,430 --> 00:10:42,420 We've seen how to capture state using implicit moves 239 00:10:42,420 --> 00:10:45,240 and maybe an explicit move using the 'move' keyword. 240 00:10:45,240 --> 00:10:48,000 And then finally, we've looked at the role of channels 241 00:10:48,000 --> 00:10:51,270 as the easiest way to communicate data between threads. 242 00:10:51,270 --> 00:10:52,103 Lovely.