1 00:00:06,510 --> 00:00:08,430 - Right time for an example of all this, 2 00:00:08,430 --> 00:00:11,670 is in the usual project, lesson six, scope ownership. 3 00:00:11,670 --> 00:00:13,350 And we are going to look at this file here, 4 00:00:13,350 --> 00:00:14,940 demo static local. 5 00:00:14,940 --> 00:00:17,190 I'm going to run the application several times, 6 00:00:17,190 --> 00:00:21,570 with different code tweaks to illustrate particular points. 7 00:00:21,570 --> 00:00:24,360 So let's go into the code and have a look. 8 00:00:24,360 --> 00:00:25,410 Right here we are. 9 00:00:25,410 --> 00:00:29,610 So it's demo static local. 10 00:00:29,610 --> 00:00:32,957 I've got quite a few things I want to explain here. 11 00:00:32,957 --> 00:00:37,560 I'm going to be doing some sleeping in my code. 12 00:00:37,560 --> 00:00:39,240 I'm going to be doing some some code. 13 00:00:39,240 --> 00:00:40,950 I'll sleep for a few seconds 14 00:00:40,950 --> 00:00:42,934 and then I'll run some more code. 15 00:00:42,934 --> 00:00:45,480 So I'm going to be importing 16 00:00:45,480 --> 00:00:48,750 I'm going to be importing the lazy structure 17 00:00:48,750 --> 00:00:52,770 which is defined in the sync module in a crate, 18 00:00:52,770 --> 00:00:56,610 which is like an additional library, called once cell. 19 00:00:56,610 --> 00:00:59,970 When you import, when you use libraries in Rust, 20 00:00:59,970 --> 00:01:02,057 most of the libraries, most of the functions 21 00:01:02,057 --> 00:01:03,540 and things that you're going to use, 22 00:01:03,540 --> 00:01:05,400 are in the standard crate. 23 00:01:05,400 --> 00:01:08,820 So for example the standard crate has a module 24 00:01:08,820 --> 00:01:11,760 called thread, which has a sleep function. 25 00:01:11,760 --> 00:01:15,030 And the standard crate has a module called time, 26 00:01:15,030 --> 00:01:16,860 which has a duration structure. 27 00:01:16,860 --> 00:01:20,250 Basically things that start with a capital are types, 28 00:01:20,250 --> 00:01:24,060 like structures or enums or traits, 29 00:01:24,060 --> 00:01:25,500 and things that start with the lowercase 30 00:01:25,500 --> 00:01:27,088 are usually functions. 31 00:01:27,088 --> 00:01:29,970 So the duration structure 32 00:01:29,970 --> 00:01:32,520 and the sleep function are in the standard crate. 33 00:01:32,520 --> 00:01:35,640 They're automatically available in the application. 34 00:01:35,640 --> 00:01:39,360 But the once cell crate, we have to actually add 35 00:01:39,360 --> 00:01:42,240 as a dependency to download into our application. 36 00:01:42,240 --> 00:01:43,740 And I've done that in the toml file. 37 00:01:43,740 --> 00:01:46,140 This is the first time we've actually seen 38 00:01:46,140 --> 00:01:49,980 an additional crate needed to be specified as a dependency. 39 00:01:49,980 --> 00:01:54,120 So once cell is a crate that I need to download 40 00:01:54,120 --> 00:01:55,230 into my application, 41 00:01:55,230 --> 00:01:58,199 chrono is another one, another dependency. 42 00:01:58,199 --> 00:02:01,800 So my dependencies, I pull in the current version 43 00:02:01,800 --> 00:02:03,600 of the one cell crate. 44 00:02:03,600 --> 00:02:05,370 A crate is like a library. 45 00:02:05,370 --> 00:02:08,490 And I also pull in the chrono library as well. 46 00:02:08,490 --> 00:02:10,290 The star is basically the current version. 47 00:02:10,290 --> 00:02:12,210 There are other versions I could specify 48 00:02:12,210 --> 00:02:14,550 and it'll just download the current version 49 00:02:14,550 --> 00:02:16,260 into my local directory structure. 50 00:02:16,260 --> 00:02:18,960 It'll be downloaded into my current project directory. 51 00:02:19,800 --> 00:02:21,890 Okay, so let's go back into the code then. 52 00:02:21,890 --> 00:02:26,890 So lazy is a structure in the sync module 53 00:02:27,090 --> 00:02:31,830 in the one cell crate, date, time and UTC. 54 00:02:31,830 --> 00:02:36,190 Both of those are structures defined in the chrono crate 55 00:02:37,230 --> 00:02:41,085 and in my demo I've got two different parts to the demo. 56 00:02:41,085 --> 00:02:44,160 I've got a call, a function which illustrates how 57 00:02:44,160 --> 00:02:46,680 to initialize statics at compile time. 58 00:02:46,680 --> 00:02:48,420 Let's have a look at that function first. 59 00:02:48,420 --> 00:02:49,680 Simple enough. 60 00:02:49,680 --> 00:02:52,740 I've got a static string, effectively a string, 61 00:02:52,740 --> 00:02:56,040 slice technically, but we'll just call it a string 62 00:02:56,040 --> 00:02:56,873 for now. 63 00:02:56,873 --> 00:02:59,460 And I've given it a compiled time constant. 64 00:02:59,460 --> 00:03:00,930 How is your Welsh today? 65 00:03:00,930 --> 00:03:04,503 Croeso o Gymru, welcome from Wales. 66 00:03:05,340 --> 00:03:06,900 And I print the message. 67 00:03:06,900 --> 00:03:09,249 So when you have a compile time value 68 00:03:09,249 --> 00:03:11,967 to assign to a string that will actually be initialized 69 00:03:11,967 --> 00:03:15,780 at compile time, it will initialize that static variable. 70 00:03:15,780 --> 00:03:17,310 And it's not multiple. 71 00:03:17,310 --> 00:03:20,130 So it's fixed to be Croeso o Gymru. 72 00:03:20,130 --> 00:03:21,990 So that's the first function call. 73 00:03:21,990 --> 00:03:25,440 The second function call is much more interesting. 74 00:03:25,440 --> 00:03:27,600 So let's have a look at this. 75 00:03:27,600 --> 00:03:29,400 Let me talk you through this function. 76 00:03:29,400 --> 00:03:32,490 This is where I want to initialize the static at runtime, 77 00:03:32,490 --> 00:03:34,860 when the program is actually executing. 78 00:03:34,860 --> 00:03:37,953 So this first statement won't work. 79 00:03:39,120 --> 00:03:42,240 You can't initialize a static directly at runtime 80 00:03:42,240 --> 00:03:44,130 because it's not thread safe. 81 00:03:44,130 --> 00:03:47,190 If you try to, you'll get a compile error. 82 00:03:47,190 --> 00:03:51,300 Let's try to initialize a static with a runtime value 83 00:03:51,300 --> 00:03:52,627 with a function called at runtime, 84 00:03:52,627 --> 00:03:56,820 call that function and assign the result to a static. 85 00:03:56,820 --> 00:03:59,864 Won't let me do it because it's not thread safe. 86 00:03:59,864 --> 00:04:03,060 Okay, well let's prove the point that that's not gonna work. 87 00:04:03,060 --> 00:04:06,183 I'm gonna try to do a cargo check. 88 00:04:07,200 --> 00:04:09,093 Okay, just to check my code. 89 00:04:09,930 --> 00:04:12,630 Right, cannot, oh, what's this saying here. 90 00:04:12,630 --> 00:04:15,840 It's basically saying here, it cannot call this function. 91 00:04:15,840 --> 00:04:19,080 I can't call that function, because it's a runtime function. 92 00:04:19,080 --> 00:04:20,700 It's not a constant value, 93 00:04:20,700 --> 00:04:23,370 it's something that has to be evaluated at runtime. 94 00:04:23,370 --> 00:04:24,990 So the error message is starting to get 95 00:04:24,990 --> 00:04:26,370 a little bit technical. 96 00:04:26,370 --> 00:04:30,960 Oh, consider wrapping this expression in a lazy wrapper. 97 00:04:30,960 --> 00:04:33,210 Well, funny you should say that. 98 00:04:33,210 --> 00:04:34,200 That's exactly what I've done. 99 00:04:34,200 --> 00:04:36,843 So let me get rid of that error message. 100 00:04:37,800 --> 00:04:39,720 And let's see. 101 00:04:39,720 --> 00:04:43,210 Now what I've done here, is I've fixed the error message 102 00:04:44,070 --> 00:04:46,773 and then I'll explain the code and then we'll run it. 103 00:04:47,820 --> 00:04:51,180 I've got an element of sleep involved here to actually show 104 00:04:51,180 --> 00:04:53,130 the time changing basically. 105 00:04:53,130 --> 00:04:55,830 So initially I print the current time, 106 00:04:55,830 --> 00:04:59,894 the UTC structure has a now function. 107 00:04:59,894 --> 00:05:02,910 It returns the current date and time 108 00:05:02,910 --> 00:05:05,100 in universal coordinator time. 109 00:05:05,100 --> 00:05:07,260 So basically Greenwich meantime. 110 00:05:07,260 --> 00:05:09,681 And when you have a UTC object, 111 00:05:09,681 --> 00:05:11,760 you can call the format function. 112 00:05:11,760 --> 00:05:14,430 It basically contains the date and the time. 113 00:05:14,430 --> 00:05:19,080 You can tell it to format a string containing just the time. 114 00:05:19,080 --> 00:05:19,913 Okay? 115 00:05:19,913 --> 00:05:21,510 So if you want details of all the formatting, 116 00:05:21,510 --> 00:05:22,860 I won't go into it here. 117 00:05:22,860 --> 00:05:25,290 Have a look at the UTC structure. 118 00:05:25,290 --> 00:05:26,760 Have a look at the format function 119 00:05:26,760 --> 00:05:28,350 and it'll tell you what different parameters 120 00:05:28,350 --> 00:05:31,710 you can pass in here to output the date time as you want. 121 00:05:31,710 --> 00:05:36,262 This will output the current time percent T for time, okay? 122 00:05:36,262 --> 00:05:41,262 So display the time when the function first enters. 123 00:05:41,790 --> 00:05:44,400 And then I've got a static variable 124 00:05:44,400 --> 00:05:48,600 which is going to be initialized using lazy initialization. 125 00:05:48,600 --> 00:05:51,720 It will effectively be a date, time, 126 00:05:51,720 --> 00:05:53,130 universal coordinated time, 127 00:05:53,130 --> 00:05:56,220 but it'll have to be initialized lazily. 128 00:05:56,220 --> 00:06:00,960 And I give it a lazy object that will create a lazy object 129 00:06:00,960 --> 00:06:04,530 with a closure, an anonymous function if you like, 130 00:06:04,530 --> 00:06:05,790 or a lambda. 131 00:06:05,790 --> 00:06:09,060 That lambda will be invoked the first time 132 00:06:09,060 --> 00:06:11,490 I try to access that variable. 133 00:06:11,490 --> 00:06:13,680 Okay, and only at that point. 134 00:06:13,680 --> 00:06:18,210 So down here I try to access the variable timestamp, 135 00:06:18,210 --> 00:06:19,803 is a lazy object. 136 00:06:20,970 --> 00:06:25,380 The contents of that lazy object will be a date time. 137 00:06:25,380 --> 00:06:27,930 Okay, so I tried to dereference the lazy object 138 00:06:27,930 --> 00:06:31,890 I tried to get the contents of the value inside it 139 00:06:31,890 --> 00:06:35,940 and at that point it will trigger the first time 140 00:06:35,940 --> 00:06:38,040 I try to access the content of the lazy 141 00:06:38,040 --> 00:06:42,318 it'll call the lambda at that point in time. 142 00:06:42,318 --> 00:06:45,300 And at that point in time, I sleep. 143 00:06:45,300 --> 00:06:47,820 Sleep remember was the function that I imported 144 00:06:47,820 --> 00:06:50,190 from the thread module. 145 00:06:50,190 --> 00:06:53,430 That's the way that you sleep the current thread. 146 00:06:53,430 --> 00:06:56,100 So I sleep the current thread, 147 00:06:56,100 --> 00:06:59,373 and the sleep function takes an a duration object, 148 00:07:00,330 --> 00:07:01,500 which makes sense. 149 00:07:01,500 --> 00:07:03,930 I've created a duration object here, 150 00:07:03,930 --> 00:07:07,170 I specified I want to wait for five seconds 151 00:07:07,170 --> 00:07:09,270 and zero nanoseconds. 152 00:07:09,270 --> 00:07:11,400 The duration new function, 153 00:07:11,400 --> 00:07:13,830 you give it a seconds as the first parameter, 154 00:07:13,830 --> 00:07:16,710 and nanoseconds, additional nanoseconds 155 00:07:16,710 --> 00:07:17,910 as the second parameter. 156 00:07:17,910 --> 00:07:20,370 So the current thread will sleep for five seconds. 157 00:07:20,370 --> 00:07:25,370 Remember this closure is being invoked kind of here. 158 00:07:26,100 --> 00:07:28,953 So at that moment it'll sleep for five seconds. 159 00:07:30,540 --> 00:07:34,173 Get the time after that five seconds, okay? 160 00:07:35,159 --> 00:07:37,320 And display it. 161 00:07:37,320 --> 00:07:40,800 It'll display the current time after five seconds 162 00:07:40,800 --> 00:07:45,513 and whatever you return from this closure, 163 00:07:46,860 --> 00:07:49,110 this value that you return is the value 164 00:07:49,110 --> 00:07:50,850 that this then will be. 165 00:07:50,850 --> 00:07:54,570 So if you follow the logic, when my application starts 166 00:07:54,570 --> 00:07:57,333 the current time will be now. 167 00:07:58,350 --> 00:08:00,810 Five seconds will elapse 168 00:08:00,810 --> 00:08:04,350 before I evaluate the value for my timestamp. 169 00:08:04,350 --> 00:08:07,320 So the timestamp will effectively be five seconds later 170 00:08:07,320 --> 00:08:09,000 than the initial time. 171 00:08:09,000 --> 00:08:11,670 So the initial time will be x, 172 00:08:11,670 --> 00:08:15,570 the timestamp will be x plus five seconds. 173 00:08:15,570 --> 00:08:17,340 Okay, so hopefully that makes sense. 174 00:08:17,340 --> 00:08:20,040 Let's actually run the application from main. 175 00:08:20,040 --> 00:08:23,340 So in my main code I'm going to invoke 176 00:08:23,340 --> 00:08:25,770 demo static local do it. 177 00:08:25,770 --> 00:08:27,660 Let's uncomment that statement 178 00:08:27,660 --> 00:08:28,890 and let's run the application. 179 00:08:28,890 --> 00:08:30,540 I'm gonna go back into the code here 180 00:08:30,540 --> 00:08:33,000 just so we can kind of see what's going to happen. 181 00:08:33,000 --> 00:08:34,083 Cargo run. 182 00:08:38,100 --> 00:08:40,000 Okay, so there's the five seconds wait 183 00:08:41,310 --> 00:08:42,870 and that's the output. 184 00:08:42,870 --> 00:08:47,870 So in demo static local, that was just here 185 00:08:50,490 --> 00:08:55,320 it output the simple Croeso o Gymru, welcome from Wales 186 00:08:55,320 --> 00:08:56,700 you are very welcome. 187 00:08:56,700 --> 00:08:59,940 And then it came into the initialization at runtime, 188 00:08:59,940 --> 00:09:02,640 which is all together more interesting. 189 00:09:02,640 --> 00:09:04,680 It output the current time 190 00:09:04,680 --> 00:09:08,603 at the beginning of that function, which was 11:51:45, okay? 191 00:09:12,270 --> 00:09:15,270 Then I tried to access the timestamp 192 00:09:15,270 --> 00:09:16,890 which will trigger this call, 193 00:09:16,890 --> 00:09:20,460 this code, to be executed just in time. 194 00:09:20,460 --> 00:09:22,440 Sleeps for five seconds. 195 00:09:22,440 --> 00:09:25,650 So the time here will be five seconds later. 196 00:09:25,650 --> 00:09:28,740 That's the current time, five seconds later. 197 00:09:28,740 --> 00:09:33,740 Okay, so that's 11:51:50, five seconds later than it was 198 00:09:34,350 --> 00:09:38,130 that's the time that I assigned to my timestamp. 199 00:09:38,130 --> 00:09:41,310 And that's the value of the timestamp here. 200 00:09:41,310 --> 00:09:43,653 Okay, five seconds greater than that. 201 00:09:45,090 --> 00:09:47,850 So an interesting thing is that this static 202 00:09:47,850 --> 00:09:52,533 only gets initialized the first time that it's used. 203 00:09:53,580 --> 00:09:55,500 If I didn't use this timestamp, 204 00:09:55,500 --> 00:09:57,480 imagine I didn't actually use the timestamp, 205 00:09:57,480 --> 00:10:00,090 I'm just gonna comment that line out. 206 00:10:00,090 --> 00:10:02,910 Then what do you think would happen now? 207 00:10:02,910 --> 00:10:04,200 Gonna run it and see if you can think 208 00:10:04,200 --> 00:10:05,400 what's gonna happen now. 209 00:10:07,710 --> 00:10:09,390 Well look at that. 210 00:10:09,390 --> 00:10:11,490 Is that what you expected? 211 00:10:11,490 --> 00:10:15,663 It came into here and it said the current time is 11:53:17. 212 00:10:18,635 --> 00:10:22,080 It recognized this lazy constructor, 213 00:10:22,080 --> 00:10:24,090 but it hasn't called this lambda 214 00:10:24,090 --> 00:10:28,410 until we use timestamp and because we didn't use timestamp, 215 00:10:28,410 --> 00:10:29,970 it is lazy. 216 00:10:29,970 --> 00:10:34,590 It only evaluates the closure at the first time you need it. 217 00:10:34,590 --> 00:10:36,480 And if you never actually use it 218 00:10:36,480 --> 00:10:38,190 then it never bothers running the code. 219 00:10:38,190 --> 00:10:40,200 Why bother running the code 220 00:10:40,200 --> 00:10:41,850 if you're never gonna use the value? 221 00:10:41,850 --> 00:10:43,353 It is actually lazy, 222 00:10:44,400 --> 00:10:47,400 and the other thing to note is that it'll only run that code 223 00:10:47,400 --> 00:10:49,650 the first time you try to access it. 224 00:10:49,650 --> 00:10:53,610 So what would it happen if I did this? 225 00:10:53,610 --> 00:10:56,880 Let's say I basically call that function, 226 00:10:56,880 --> 00:11:00,450 that code twice and I have a little sleep in here. 227 00:11:00,450 --> 00:11:02,043 I'm gonna copy this code, 228 00:11:03,390 --> 00:11:05,040 so I don't have to repeat myself. 229 00:11:06,240 --> 00:11:08,580 So what do you think is gonna happen now? 230 00:11:08,580 --> 00:11:09,540 Let's just run it 231 00:11:09,540 --> 00:11:12,440 and give you a chance to think of what's gonna happen now. 232 00:11:14,640 --> 00:11:15,903 And waiting patiently, 233 00:11:17,340 --> 00:11:18,790 waiting very, very patiently. 234 00:11:21,780 --> 00:11:23,580 Right, let's go through what happened then. 235 00:11:23,580 --> 00:11:28,403 So current time initially was 11:54:25. 236 00:11:29,730 --> 00:11:32,190 I declared my static and the compiler 237 00:11:32,190 --> 00:11:34,710 or at runtime it said, "Right, okay, I'll bear that in mind. 238 00:11:34,710 --> 00:11:36,120 I'll bear in mind that's the code 239 00:11:36,120 --> 00:11:38,970 but I won't run it until the first access." 240 00:11:38,970 --> 00:11:40,530 Well, here's the first access. 241 00:11:40,530 --> 00:11:43,140 So at that point it did have to run the code, 242 00:11:43,140 --> 00:11:45,170 when I call on line 36. 243 00:11:45,170 --> 00:11:48,840 At that point it did have to access to run the lambda. 244 00:11:48,840 --> 00:11:53,730 So it ran the lambda at that point, waited for five seconds, 245 00:11:53,730 --> 00:11:56,910 output the current time after five seconds. 246 00:11:56,910 --> 00:12:00,900 And then that value is the value of my timestamp variable. 247 00:12:00,900 --> 00:12:03,510 Okay, so there's the five second wait 248 00:12:03,510 --> 00:12:08,400 and then the timestamp variable here is five seconds later 249 00:12:08,400 --> 00:12:11,520 than the variable initially up here. 250 00:12:11,520 --> 00:12:14,910 I sleep for five seconds, okay. 251 00:12:14,910 --> 00:12:16,950 And then I access the timestamp. 252 00:12:16,950 --> 00:12:20,370 The timestamp available is only initialized once, okay? 253 00:12:20,370 --> 00:12:22,560 So it doesn't repeat the code. 254 00:12:22,560 --> 00:12:25,260 It already has an initial value 255 00:12:25,260 --> 00:12:28,350 when it ran the the lambda the first time. 256 00:12:28,350 --> 00:12:33,300 So for the second time the value is the same as before. 257 00:12:33,300 --> 00:12:36,330 Okay, so it only initialized the value, 258 00:12:36,330 --> 00:12:37,890 it only ran the closure, 259 00:12:37,890 --> 00:12:40,590 the first time we accessed variable here. 260 00:12:40,590 --> 00:12:42,660 The second time we access it, 261 00:12:42,660 --> 00:12:44,103 it already had available. 262 00:12:44,970 --> 00:12:48,900 Okay, so it is quite involved, much harder work 263 00:12:48,900 --> 00:12:51,420 than you'd been used to from C and C++. 264 00:12:51,420 --> 00:12:54,960 The whole point is that even though it's harder work, 265 00:12:54,960 --> 00:12:56,520 it is thread safe. 266 00:12:56,520 --> 00:12:59,120 Okay, so ultimately that's the most important thing.