1 00:00:00,000 --> 00:00:07,966 [No Audio] 2 00:00:07,967 --> 00:00:10,230 Welcome back again. This tutorial is about a 3 00:00:10,231 --> 00:00:13,066 special feature of Rust for threads called Park. 4 00:00:13,366 --> 00:00:15,420 The park will block the execution of 5 00:00:15,421 --> 00:00:18,450 the current thread until it is unparked. You 6 00:00:18,451 --> 00:00:19,980 may find it quite useful in your 7 00:00:19,981 --> 00:00:22,170 synchronization problem. So let us start 8 00:00:22,171 --> 00:00:24,540 learning it. I will first bring the relevant 9 00:00:24,541 --> 00:00:25,740 modules into scope. 10 00:00:25,741 --> 00:00:30,810 [No Audio] 11 00:00:30,811 --> 00:00:33,600 Next, I will create a thread called job_1. 12 00:00:33,601 --> 00:00:37,700 [No Audio] 13 00:00:37,701 --> 00:00:39,330 Inside the thread, I will add a 14 00:00:39,331 --> 00:00:41,550 print statement to indicate that the 15 00:00:41,580 --> 00:00:42,966 thread has started. 16 00:00:42,967 --> 00:00:47,433 [No Audio] 17 00:00:47,434 --> 00:00:48,660 Next, I want to stop the 18 00:00:48,661 --> 00:00:51,030 execution of this thread for some time, so 19 00:00:51,031 --> 00:00:53,600 that another thread containing job_2 20 00:00:53,601 --> 00:00:56,010 is started and goes to completion. So I 21 00:00:56,011 --> 00:00:58,200 will add a print statement to indicate this. 22 00:00:58,201 --> 00:01:04,709 [No Audio] 23 00:01:04,710 --> 00:01:06,509 To stop the execution of the thread or 24 00:01:06,510 --> 00:01:08,969 suspend its execution for some time, we need 25 00:01:08,970 --> 00:01:10,349 to use the park function. 26 00:01:10,350 --> 00:01:15,420 [No Audio] 27 00:01:15,421 --> 00:01:18,166 This will block the current thread or job_1, 28 00:01:18,167 --> 00:01:20,100 until we explicitly resume it 29 00:01:20,101 --> 00:01:22,770 using the unpark function. When the thread is 30 00:01:22,771 --> 00:01:24,750 unparked, the remaining of the code in this 31 00:01:24,751 --> 00:01:27,630 thread will be executed. I will add a suitable 32 00:01:27,631 --> 00:01:29,670 print statement to indicate the resumption of 33 00:01:29,671 --> 00:01:30,733 the thread code. 34 00:01:30,734 --> 00:01:36,000 [No Audio] 35 00:01:36,001 --> 00:01:38,866 Let us now define another thread called job_2. 36 00:01:38,867 --> 00:01:42,966 [No Audio] 37 00:01:42,967 --> 00:01:44,010 We want this thread to 38 00:01:44,011 --> 00:01:47,300 complete before the thread with handle of job_1. 39 00:01:47,733 --> 00:01:49,530 I will just include some 40 00:01:49,531 --> 00:01:51,810 simple print statements inside this thread. 41 00:01:51,811 --> 00:01:59,069 [No Audio] 42 00:01:59,070 --> 00:02:01,409 Outside the thread, I will call the join on 43 00:02:01,410 --> 00:02:03,419 job_2 to make sure that it 44 00:02:03,420 --> 00:02:04,889 goes to completion first. 45 00:02:04,890 --> 00:02:12,420 [No Audio] 46 00:02:12,421 --> 00:02:14,190 I will add a suitable print statement to 47 00:02:14,191 --> 00:02:17,300 indicate that the job_2 thread is now complete. 48 00:02:17,301 --> 00:02:23,310 [No Audio] 49 00:02:23,311 --> 00:02:26,000 Next, I want to resume the job_1 thread. 50 00:02:26,133 --> 00:02:28,666 First, I will include a suitable print statement. 51 00:02:28,667 --> 00:02:33,033 [No Audio] 52 00:02:33,034 --> 00:02:34,770 Next, I will make a call to the 53 00:02:34,794 --> 00:02:37,344 unpark on job_1, this will 54 00:02:37,345 --> 00:02:40,066 resume the execution of the job_1 thread. 55 00:02:40,500 --> 00:02:42,180 Finally, I will make sure that the 56 00:02:42,181 --> 00:02:44,340 job_1 thread goes to completion, 57 00:02:44,341 --> 00:02:47,233 so I will call the join on job_1 thread. 58 00:02:47,234 --> 00:02:51,666 [No Audio] 59 00:02:51,667 --> 00:02:53,733 Let us cargo run this now a few times. 60 00:02:53,734 --> 00:03:03,720 [No Audio] 61 00:03:03,768 --> 00:03:05,868 You may note that during each execution, the 62 00:03:05,869 --> 00:03:08,100 job_2 is first completed, and 63 00:03:08,101 --> 00:03:10,980 only then job_1 goes to completion. Similar 64 00:03:10,981 --> 00:03:13,320 to the thread park, there is another function 65 00:03:13,321 --> 00:03:16,170 called park_timeout. This will 66 00:03:16,200 --> 00:03:18,810 essentially block the current thread for some 67 00:03:18,840 --> 00:03:21,390 specified time interval. The thread will be 68 00:03:21,391 --> 00:03:23,580 unblocked if during this interval the thread 69 00:03:23,604 --> 00:03:26,184 is being unparked. If no unpark is being 70 00:03:26,185 --> 00:03:27,960 called, then the thread will be blocked 71 00:03:27,990 --> 00:03:30,900 until the time duration ends. Let us see this 72 00:03:30,930 --> 00:03:33,240 in the same program. Instead of the thread 73 00:03:33,241 --> 00:03:36,360 park function, I will now call the thread, the 74 00:03:36,361 --> 00:03:39,060 thread::park_timeout function with 75 00:03:39,061 --> 00:03:41,280 some duration in seconds. This will 76 00:03:41,310 --> 00:03:44,940 essentially blocks unless or until the 77 00:03:44,941 --> 00:03:47,370 current thread token is made available, or the 78 00:03:47,371 --> 00:03:49,300 specified duration has been reached. 79 00:03:50,533 --> 00:03:53,340 Now what will happen is that, the job_1 80 00:03:53,341 --> 00:03:55,260 will be blocked until the duration of 2 81 00:03:55,261 --> 00:03:58,110 seconds expires, or when it is being unparked. 82 00:03:58,120 --> 00:03:59,576 Let us execute. 83 00:03:59,577 --> 00:04:04,860 [No Audio] 84 00:04:04,861 --> 00:04:07,500 In this case, the thread or job_1 85 00:04:07,501 --> 00:04:09,990 resumed immediately before the expiration 86 00:04:09,991 --> 00:04:12,630 of the time interval. Let us comment out the 87 00:04:12,631 --> 00:04:15,966 thread unpark for job_1 and execute again. 88 00:04:15,967 --> 00:04:22,560 [No Audio] 89 00:04:22,561 --> 00:04:24,510 In this case, you may note that it took some 90 00:04:24,511 --> 00:04:26,130 time. This is because the thread 91 00:04:26,131 --> 00:04:28,050 corresponding to job_1 was 92 00:04:28,051 --> 00:04:30,960 parked for two seconds and it completed the 93 00:04:30,961 --> 00:04:33,540 two seconds since nobody else unparked the 94 00:04:33,541 --> 00:04:35,820 thread. Please note that there is a very 95 00:04:35,821 --> 00:04:38,370 similar function to the thread park, and the 96 00:04:38,371 --> 00:04:41,033 thread::park_timeout called a thread::sleep. 97 00:04:41,183 --> 00:04:42,500 Let me also use it. 98 00:04:42,501 --> 00:04:45,866 [No Audio] 99 00:04:45,867 --> 00:04:47,250 This function will block the 100 00:04:47,251 --> 00:04:49,530 current thread for the specified amount of 101 00:04:49,531 --> 00:04:51,690 time. The main difference of this function 102 00:04:51,691 --> 00:04:54,060 with the thread::park_timeout function is that, 103 00:04:54,210 --> 00:04:56,070 this function will completely block the 104 00:04:56,071 --> 00:04:58,380 thread for the indicated amount of time with 105 00:04:58,381 --> 00:05:00,930 no way of resuming back thread before the 106 00:05:00,931 --> 00:05:03,810 time expires. Even the calls to the thread 107 00:05:03,840 --> 00:05:06,480 unpark will not work. Let me comment out the 108 00:05:06,481 --> 00:05:09,166 thread unpark function and execute now to confirm. 109 00:05:09,167 --> 00:05:13,933 [No Audio] 110 00:05:13,934 --> 00:05:15,480 Lastly, there is another useful 111 00:05:15,481 --> 00:05:18,210 function called yield_now, when a thread 112 00:05:18,211 --> 00:05:20,430 calls this function, it will cooperatively 113 00:05:20,431 --> 00:05:22,530 gives up its turn to the operating system, 114 00:05:22,531 --> 00:05:24,300 telling the operating system that I am 115 00:05:24,301 --> 00:05:26,130 willing to give out my running time to 116 00:05:26,131 --> 00:05:29,130 someone else. This generates a signal from 117 00:05:29,131 --> 00:05:31,650 the calling thread that is, it is willing to 118 00:05:31,651 --> 00:05:34,020 give up its remaining time slice so that the 119 00:05:34,021 --> 00:05:36,300 operating system may schedule other threads 120 00:05:36,301 --> 00:05:39,450 on the CPU. Let us use this function in the 121 00:05:39,451 --> 00:05:41,910 job_1 thread, I will comment out 122 00:05:41,911 --> 00:05:43,366 the call to the sleep function. 123 00:05:43,367 --> 00:05:46,966 [No Audio] 124 00:05:46,967 --> 00:05:49,033 Now, let us call the yield_now function. 125 00:05:51,253 --> 00:05:54,275 What this will mean that the job_1 will 126 00:05:54,276 --> 00:05:56,495 yield back to the operating system, which will 127 00:05:56,640 --> 00:05:58,770 enable the operating system to schedule some 128 00:05:58,800 --> 00:06:02,000 other thread for execution. The operating 129 00:06:02,001 --> 00:06:03,360 system will therefore either 130 00:06:03,361 --> 00:06:05,640 execute the job_2 thread or the 131 00:06:05,641 --> 00:06:08,700 main thread. The overall effect of this will 132 00:06:08,701 --> 00:06:11,100 be that the job_1 may go to completion late, 133 00:06:11,101 --> 00:06:13,470 because it is yielding back and therefore 134 00:06:13,471 --> 00:06:16,020 giving more chance to the job_2 135 00:06:16,021 --> 00:06:18,930 and the main function. Let us execute a few 136 00:06:18,931 --> 00:06:20,322 times to see the result. 137 00:06:20,323 --> 00:06:26,279 [No Audio] 138 00:06:26,303 --> 00:06:28,703 You may not get the job_1 is always 139 00:06:28,704 --> 00:06:30,449 completing late due to the fact that it 140 00:06:30,450 --> 00:06:32,699 is yielding back to the operating system. 141 00:06:33,359 --> 00:06:35,159 That brings us to the end of this tutorial. 142 00:06:35,160 --> 00:06:37,215 See you again and until next tutorial. 143 00:06:37,216 --> 00:06:38,866 Happy Rust programming. 144 00:06:38,867 --> 00:06:44,166 [No Audio]