He he said something at the very end. He said something like looks cool or something like that and you know like my brain froze It's like word said my thing looks cool or something, you know, like That's nice It's also super funny. I don't think I told this story I don't think you were a place where I told this. I know I told this story, but I think it was another place So you haven't heard this yet, right? Ward has got that total since I've said it since I vibe and you did hear this story you did say it It's so weird watching people watching Watching Ward say something that nobody agrees with but no one is going to like And it wasn't for like anything informational like like wiki stuff, you know, that's like, okay, whatever, you know But it was like where I think it was where we're the first one the first wiki birthday call Like the last couple minutes. I think was mark Marker John Abbey one of them said and we wanted to talk a little bit about plans for you know coming up The 30th the mean oh we should make plans Ward shut down the call. He's like You know, I think we've had a great call. I think I'll leave Everyone's like, okay, I guess we're filing out Anyway, so we did get to talk about that in the second call But then the surprise then was you know, well, where should we hold this recent changes camp and somebody's like everybody's quiet Waiting for Ward to say something and finally somebody says one acolyte says I think we should do it in Portland because that's the place of the first You know RCC and and it's you know, Ward's place and word says How about the Midwest? It seems like that would be a better place for all the people who might attend, you know So I was like, okay, whatever Ward has spoken as long as it's not Chicago in December Detroit in March End of March. I'm adding a thought to my brain from the 2025 RCC for the 30th anniversary I mean, this is next year, right? Yeah, yes Next year on March 25, I think because that was the date. It's all right. Yes What's the event? Sorry. I came in late wiki birthday This last Monday was the 29th anniversary of the first wiki And we had we had two wiki birthday calls with Ward and you know some of the old-timers Cool, were they recorded? Are they posted any place? John recorded the first one. I don't think it's gonna get distributed and the second one wasn't recorded. Oh, that's too bad. Oh Pete could I ask you for the recording of yesterday's the I entrepreneurs called you forward me the zoom download link Thanks I'm gonna trim the end of it off and post it and listen to YouTube. Oh, okay, perfect. Thank you I was gonna do something off of the same. Thank you Sorry to make more work for you No, no, no, you know So I set up two new wiki communication channels there it's not that I Read their recent changes camp channels one in matrix and one in CSC matter most nobody's joined yet except bill Anderson. I guess Matter most one. Let me announce them here Did you announce it in town square I Didn't tonight. It's I did actually I Know that's it in massive wiki the massive wiki channel in Unfortunately, I didn't hail I had done two hails in a row and I'm like I'm not gonna hail on this one I mean that was the one that I should have So here's massive wiki These are changes count matrix on matrix and here's Massive wiki one Good I'm in Now there's three of us Hey, what's new and exciting? What's the name of the app that automates things Pete that Pete that you turned us on to you. Oh Yes, yes, it's called Cassidy and It's a bad sign that I my unaided recall of Cassidy is shitty. I have three times now I've tried to remember its name and I don't remember its name. I Think that's actually not a bad sign The a lot of the market marketing is gonna be viral so it's actually okay if you don't quite remember the name Yeah, but I can't tell anybody about it without looking it up. That's really bad Well, but now you've looked it up now. You like double remember now now it might Well, so I was gonna call it a Claudius So so unaided recall was close to the with a starting letter which is typical for me I usually remember starting letters and stuff, but I had no Cassidy was not in my head at all Maybe now and if it takes you four tries to remember a name that's miserable for product naming Unless unless they do something to make it stick I think it's it's bad for individuals and it's not bad for social So it's my prediction I've been waxing poetic about Cassidy, uh, it's it's uh somebody Justin Feinberg, I don't know if you know him or not. Um Jason just I think it's Justin um He and a team put together office automation for Like a small business or something like that with LOMs And I was pretty blown away by the demo It seems really powerful. It's sort of like if this than that only done bigger better with some machine intelligence What does it accomplish? Like what is it doing? It it does the informational things that you would do if you were like, uh, the president If you were running a small business if you ran a small business you'd need people to Watch the email do research for you help you You know do customer support all that kind of stuff It's kind of instead of just well, I'm probably overblowing it, but instead of task automation Um, it's more like virtual employee Spec, yeah, it feels like virtual employees. Yeah Um, so if you if you think of the jump from chachi bt to gpt's Um, this is like two more jumps like that kind of um, it's you know A collection of gpt's And then they're Autonomous or semi-autonomous And you know They can cooperate and stuff like that. Uh, and work with mail email or um Or the web or You know like your common office tools kind of stuff It's also understands your corpus. It has all of your you know, whatever corpus you want it to have it has that it's got some special automation on top of that which is um Let me read through all your marketing materials. It does this It does this as a background thing basically it wants to understand the way that you present your, uh corporate voice Um, so kind of in the background of stuff that you do It learns your corporate voice by reading your marketing materials and stuff like that And then you can talk to it about that, you know, hey, let's talk You know, I need you to adjust the the way that you think about the corporate place All the instruction that you do for it all the automation stuff you do with uh, with, um Kind of like the wizard you use to set up a gpt. It's a natural language interface that says You know, hey go out and do this kind of research or when you're talking to customers do this or I need, you know In the customer support workflow, I need this to happen instead of that or whatever What's interesting is it looks like in one of their demos that gives a little footnote Presumably to give you a reference for where the answer came from It does that, you know, you know, which is nice That's the the new thing with the rag stuff. Um, Anybody who's implementing rag commercially does footnotes And and I was a little bit surprised. I don't know if this is a good thing or a bad thing I was a little bit surprised. We were watching the autonomous bot I think do tech support customer support customer support not tech support And it was writing an email to the customer And it included the footnotes in the email to the customer and I was like I don't know if I would do that Even though it was to you know, the footnotes were to their like support material on the web I you know, I don't know how many people are going to Get that I mentioned those are Statistic things you might be able to tweak. Sorry. I'm go ahead. Yeah I just gotta say I would feel like most people would like to be able To like read further into things Like When we, you know, even for a support that like our I I don't disagree, but I have a different judgment of Roy Palloy, I think I think the three of us here learned about footnotes In the time before the web even and it's like, oh, yeah, but no I think a lot of people nowadays are going to look at a little number after the thing and it's like That's weird You think that people who are using the web right now don't Know how to read footnotes I don't think that's true. I think we're all like the characters in walley We're just basically sipping our sodas getting automated stuff shipped to us with drones and shrinking inside of our bodies Our bodies our bodies are bloating as our skeletons are shrinking Exactly chris is acting it out right now Uh, there you go a related thing I think I think normal civilians on the web would be surprised and probably not Most of them won't figure out what a number after after a phrase means on the flip side Something that totally surprises me is I see normal people civilians shipping around very url Because we don't have a better way to do it basically And it's like Like people don't freak out when there's a url, you know, even if it's one of the really long ones with a bunch of tracking stuff So the other thing is people don't know how to trim the tracking stuff That's bad I try to insert a I try to chrome extension that was supposed to trim those tracking things and it didn't work for ship so Because when I when I add any url to my brain, I always clean that that stuff off the back. Yeah Yeah I don't know. I mean, yeah, I I know people are doing that. I noticed recently that um Firefox has a right-click option to copy urls without tracking. Wow so people are thinking about it right and tumblr famously runs every link through href.ly which strips all the url parameters off of it So I do think people are thinking about it and I do think people could read footnotes like people still read books Footnotes are in books people still go to school footnotes are even in in high school I think that it's I think that it's there, you know, so my guess is people don't read books And and so my guess is people don't read books and schools don't teach footnotes is that that's my My base assumption about the world I don't think that's true. I mean, maybe there are some particularly bad schools, but Uh, I mean I work with college. I've worked with college students. My partner works with college students I think in both cases generally we can rely that people understand how footnotes work I wish we could run that study I wish there was a study for hire that we could like pay 10 bucks and get that done Yeah, I'd be interested in such a study, but I I really do suspect that like dependably people are uh, you know Able to understand what a footnote is I will adjust my expectation a little not a lot Or more likely, you know Not an actual footnote, but just the url like click here to find more Is a easier grammar, I think then I think I think I so Erem I probably would both agree that people can do that Um, the thing is that gets really clunky in inline text, right when you we've got an lllm answer You really want to do it like a footnote Probably uh, well a hyperlink footnote Right, that's why I said like I do think the lllm Uh No, the uh, I do think like the what is it is it amazon or microsoft's that has footnotes in their chatbot responses. I think it's Microsoft Yeah, so like Other chatbots are looking towards that model. I think it's a good model, right like Having it having these systems acknowledge that like Data has its sources is going to be important. Yeah Yeah, I think I think it'll happen more and I think people will get trained What uh hypertext right hyper you know hyperlink footnote is I think that'll happen Yeah um Chris can ask you a dumb question about subtle custom sure so, um, my impression is that the magic of Subtle custom is the encoding scheme that lumen Created that he wrote at the top of every card And then when I look at computers, I'm like gosh, we're so so capable of more things How are people implementing subtle custom? Are they doing that weird little encoding thing? Or are they actually doing better than that like and if if not what So I think most of the space comes down to And what's interesting is they the two things were essentially created Plus or minus six months in the year 12 30 Is it's the idea of a concordance? with just raw search um and a subjective index so the vast majority of You know and there's a group of people when they say zettelkasten they mean a nicholas lumen esque zettelkasten But in practice almost none of them practice that way or use a decimal Finder or indicator And and or they don't because it's in a digital context They don't actually attach the new idea right behind or even link it directly to the another idea So when I see people showing examples of theirs Quite often they've got a lot of orphan ideas They really should be linked to something Or in a chain of things And almost never is there a chain of things in any of these graphs or if there is it's only three long and it's never It's very rarely. Do I see a digital version? That has a a chain of something like 10 or 15 deep um And because of that Really what most people are practicing is a more traditional commonplace book practice And they're putting tags on it And they're using the tags to find the stuff or they're just using raw concordance word search Look for these three words And I get 10 results and then you got a filter through the 10 results to get the one you want Which doesn't The sad part is that doesn't scale very well after you've been doing it for 20 years because you're going to get 500 You know if you're a luma and you look for sociology It's everywhere. So this is the problem with backlinks in rome and all the other back linky tools too. Yeah, so having A decimal number Attached to it is great if you're using it to and the one thing that always happened with lumen system Because of the way he did it You write down a new idea and it always gets a number And it always gets a specific place In relation to other things around it And a lot of people I see doing it. They'll write a note and they just throw it into a folder And then it's just floating out there and it's it's really attached to nothing Or maybe it's attached by a few tags Well, lumen's encoding scheme was was sort of chronological and then contextual With multiple contexts available, right? So so chronological because this is box 15 and here's where we are in box 15 No, he He didn't have time or date stamps on anything. Oh I thought he was I thought he was collecting linearly through the boxes No, no, so if you asked him he might remember it. Oh, yeah, I wrote that in this year or Such and such. Okay, but if you actually go through his physical box The digitized version There's no dates or times on any of it. Huh, and it's literally the And he's specifically not filing by Like category or topic He's take it. Here's an idea. So let's say my my first idea is peanut butter is really great And then my second idea is chocolate is really good, too I'm gonna He's not filing them both under foods Or taste or flavor or anything else, but he's like, oh chocolate and I'm Talking about taste so I'm gonna put the two together And then when he goes back and he looks at the two cards and they're right next to each other He's like, oh chocolate and peanut butter Ah, let's you know Reese's pieces. Let's make a Reese's pieces peanut butter cup And go for it. So that's kind of in tiny Aggregate that's what he's doing And that's how he's kind of using it to generate ideas interesting But his second idea if he's talking about sociology his next card that goes right behind it may be something to do with Anthropology or maybe archaeology Something totally unrelated to sociology, but he knows the two in his mind are linked in some way And over time they may become further and further apart because he's putting new cards behind individual ones But it's still at least that those ideas are in a neighborhood of space But it only works for him Because he's seen it and so half of the system is in his head right and he's able to search But if you look at his index his index is incredibly sparse So you look at his index and you'll see the word sociology pop up in german And there's only two entries what? But the whole damn thing is about sociology But the two entries he's gotten his index are kind of saying Here's roughly kind of where I would start on that topic And almost all of his index entries Are one or two entries to say go look here and in this neighborhood But and it's very rare that you see Even three or four indexed entries Unless things are very far apart and it's super duper super rare to see five or six or more Whereas most people who use like let's say obsidian They're gonna put the tag You know friends of the link on every or like you in your brain It's all friends of the link is gonna have a lot of tags on it that holds things to that one page So the more calls we have the more things you're gonna have under that search term And then in lumans version He's gonna index it once maybe twice and then never after that So I didn't realize that the neighborhood really mattered to him that that he was working spatially that way It didn't realize that at all and that makes it seem Less useful to a third person To a second. Oh, yeah to a third party searching it who doesn't know what's going on or what's where But to him having read it and having had the experience and occasionally Kind of flipping through and reviewing over it He's gonna know roughly where most things are Because he's gonna have a kind of a visual You know associative trail memory If you want to use van of our bush's terminology Yeah, but the nice thing he can do is hey, I want to write an article on this topic Look it up in the index find the neighborhood and then you can pull out a big chunk of cards from that neighborhood And they're all going to be interrelated ideas and you can then just spit out an article based on a chunk of material you pull out Um, so if you think if you want to think about it and it probably the best way to look at it um Springer verlag publishes math books at the undergraduate level but the graduate level ones are better to look at and Each theorem and definition and proposition is going to have a decimal number And they're going to be in an order logically for publishing the book um But if you think of making a book like that in reverse order You're putting all the numbers So you'll have a theorem with one number And you're obviously you would put the proof of that theorem as the next number right behind it because they're intimately linked and then you're going to have Those two things very close to the definition of the words that are in the theorem and or the proof So within that neighborhood If you're a mathematician writing a book All those things are going to tend to stay close together in a neighborhood And then when you decide to write the book you can literally pull those things out and just more or less dump them into the book And you've got the book written you may adjust one or two things And then you remember at top to bottom Chapter one gets the number one chapter two gets the number two But serum one in chapter one is one dot one One an exact example is one dot two dot So you can look at the table of contents and you may go three or four decimals deep It is an outline But then that outline will exactly match and when you look at the individual page You could cut it up and break it into little zettles That you could file you would file close to to themselves So literally writing it in reverse So they're like index so the index goes to like these neighborhoods And the neighborhoods like sort of have a landing index that the index is directing you towards That's linked to the other Items that are related to it positionally Yeah, that'd be okay And then if you want to get really crazy and you have another idea That you're not going to index You don't want to spend the time to write another index card to index a new idea That may be far away from where it might go And you want to put it somewhere else You'll go to the card that you might also write and you'll write a link A written number link down on that first card, but you'll still put it somewhere else So they're still interlinked and you can follow a trail So your index may say Go for this topic go see this card and then after you flip through four or five cards after it You'll see another link that says oh look at this other bigger crazier number way over there To find a continuation of this idea. That's also related to something else. Maybe it's politics or Whatever that thing is in your system So you're it's all interlinked but what most people don't realize is his um His index is like ridiculously sparse Thank you, I I did not I did not know that about it at all go ahead arm Yeah, are you familiar with like, um the one of the conventions that have emerged in the obsidian community is like the up and down key fields Which sort of sound related to this where you might define a File as having a file that's up above it as like sort of like ascending towards an index and then down towards deeper explorations of this idea that may like be related but not like It necessarily something that you would link in the text of that particular file Uh, does that sound sort of similar to what you're talking about in terms of like the sparse index?  It's kind of similar and if you want to think of it and I nobody I think about me has ever said or envisioned this but there is a If you think about the idea the neighborhood of ideas um You can if you're We can stick with lumans example of sociology.  So you don't want to tag anything But the more specific the tag you put on something The more valuable it gets Both for search and finding a particular idea and finding ideas in that neighborhood But as you take big top level categories and you become more and more specific The most specific tag you can put on something Is the title to the card that's most directly associated with it or that follows it um And that's so you can kind of go from the very broad general down to the super specific and the most specific is a direct link to just one other card And so then when you're looking for the one thing you're always going to find the other But then when it comes to writing about whatever the thing is and actually using all your cards to create something All the things you're going to need are going to always be Either in a specific neighborhood or within that neighborhood you're going to have Pointers that say oh grandma lives five miles away And she she belongs in this family So where you can go grab her and bring her over for the family reunion of writing Whatever the piece is you're writing Um if that makes sense and then when you're done you just file there They've all got numbers so you file them all back away where you need them But if there are kind of quirky things that I know a lot of people don't get far enough into The system to really realize What those affordances look like for them And they get um so the The initial startup cost for setting up A zettle cost and whether it's paper and index cards and tabs Or if it's in obsidian and you have to learn how obsidian works The upfront cost is big, but as you're using it over time And ostensibly not adding five million plugins that you have to keep adding the overhead for The cost of using it becomes way simpler And I what what's interesting is this week. I've actually been reading a a book from 1908 About a researcher who was talking about creating Card indexes for business use generally and he makes the exact same point And essentially he says a lot of people are using books or notebooks or ledgers in their business use And they don't use the card index system long enough to realize any of the gains Um And then the other thing too is as you're using it and you're more familiar with it The speed with which you can use it so I can write a card and I can almost Immediately imagine where to put it The that filing piece becomes nearly automatic Although I find in a lot of cases trying to do that in a digital system Where I can't see it all I have to do a search to find the thing and then make the link and then and then it's where I want it to be But it takes more work for me to do that than it does on a piece of paper in You know a big box um So the more familiar you are and the more specialized you are in the use of it The faster it becomes and the more useful it becomes I know I I've been trying to collect examples of like really good Like speed things so I'm reading a book on Poverty and there was a a history book From 19 I think 34 that I was interested in so literally I highlighted it and I typed in the year 1834 Which I do occasionally for certain historical reference things And I discovered I already have something tagged under 1834. I'm like You know, that's weird and bizarre But what it turned out to be was a reference to the poor laws in britain in 1834 the spinam line laws Which beatrice web researched and wrote about in 1910. Oh, wow and essentially said The way these laws are written they're being Implemented in different ways in different areas. So they really don't help because it's The mayor of this local city that really it's more dependent on how he applies the law To make the law useful or not And in her sociological research decades later, she essentially said these laws are so poorly written And the effects are so dismal It's just useless and so britain got rid of all those laws because she did the field work To find it and say they're totally useless. So it's And you know, that's the kind of stuff that doesn't happen now even with the us government We make these laws and then they usually they prop up institutional power And sidelined minorities in very careful ways You know and nobody's actually watching what happens five ten years later the general effects the People who are put into the minorities feel it and see it But it's hard to fight against because oh no, these are these are laws that apply to everyone, you know, it's We're doing a horrible job of that kind of stuff. So But it was interesting that because I can find a tag for 1834 I was immediately able to put this one book on poverty together with something a century and a half ago almost immediately and then the first thing I do is I look in the Index of the book I'm reading Does this author who's talking about research as poverty? Does she even and there was no reference to these laws in the 1830s in london? So it's like oh here's a brand new fresh area to like explore all this stuff in Did you find that I never in every one years would have thought or found or discovered Did you find your way because of a quirky link? Did you find it great to to the great transformation polonis book? yeah And if there's like so many books on my list that I'm reading right now for these kind of things that So everything chris everything you said is fascinating from the perspective of the neobooks project that we run on mondays One of the one of the Juicy questions we've been bumping up against a lot is how to nugget ties ideas or information And then how to recompose the nuggets into alternate narratives Uh to write a book for example or do something else and Two of the questions we haven't really answered yet, but pete and I've talked about them a bunch One of them is how do you apply metadata to make that work really well? Maybe three questions one. How do you apply metadata to how do you get related but not the same? Document or artifact together and how do you bind them so that they're near each other? So even just the trend the transcript of a video and the video itself are two objects that need to be kept close together and then three we want these Artifacts to be alive to be ever improving like a good wiki page How do you create conversations around or what is the right set? what is the kind of Crystal clear set of ways of interacting with these nuggets so that you could just like it comment on it Or actually try to improve it or actually fork it and use it in your own work And those are kind of those are kind of the levels of involvement But all of that is sort of nugget dynamics that i'm really fascinated by Well, i'm starting to think too that the big issue in a lot of these things is the difference between The concordance word search I'm looking for the word encyclopedia and things around encyclopedia And it becomes even harder when there Other words and other languages with different spellings or synonyms to encyclopedia, which is really concrete enough that that's not as big an issue But let's say i'm looking for the idea of zettle kosten but then there are Related words like commonplace book and flora legium throughout history that are related to And very similar to that and how do you find those links? and concordance search is super hard to do that And really what you want is a more subjective like book index version But because it's subjective The index you and the words you use for it are going to be different than the words peep uses for it And having all those done and most google search is usually the easy concordance Search but you're not necessarily going to find You'll find a quick answer, but you're never going to find the really great thick deep answer If that makes sense that you might find by looking in 10 well index books for the same idea you're looking for or another Kind of variation of it is Mortimer Adler's syntopicon Has 102 big key headwords And then each of underneath each of those Are more subtle shades of Kind of longer phrases or sentences relating to those words Where he's taken okay Aristotle wrote about this play to wrote about it and then centuries later montaigne touches on it and shume touches on it and Those ideas under let's say politics Or can be all wrapped up But you have to be able to delve down more deeply to find The things that are really related and that becomes a much harder Bigger group problem So you have things like um You know paul othlats mundanium Uses kind of a A key word thing But in addition to keywords he has dates and locations and time periods and and he Strings them together essentially the way you would algebraically with Plus symbols although he used different symbols so you can have Politics in the 17th century in france And then if you want to add the idea of chemistry to that What does that look like and where do you go from there? And doing that in a Kind of standardized way that is easy for everyone to use becomes a lot harder Um, so it's easy to say i'm i'm melville dewey and everybody should use the dewey system and then once everybody does it's it's simple But when you go to five ten in the math section and you find something related to politics Which would never be found in the five ten section. How do you in that book on math? You know, let's say it's in topology, so it's five twelve But it's an idea about politics in a math book. How do you How do you then figure out a way to? Standardize things so that politics idea can also be found when you're in the politics section And that's a much harder problem and a piece of the problem there is the nugget size is the book Because the book needs to get shelved in the right place where Where the book contains a whole bunch of ideas And it might contain a case study about the use of topology and politics for doing analysis or something like that And that nugget ought to be free to roam um, and you'll if you pull out let's see So I can pull out Stephen Pinker's words and rules And really here and tiny tiny print Next to my finger here Are like three subjects So the book itself will be indexed in the card catalog under A big topic probably linguistics But then the book itself usually has three or four Some maybe go up to ten Sub topics that are further away than the section you're going to find the book in So Those secondary or tertiary topics may also be indexed in your card catalog Under those Dewey decimal numbers, but then they're going to point back to the book in the linguistic section But it's still Even harder than that because you might find that politics thing that's not even listed in the front of the book So you're never in a million years going to find it in the card catalog because it's You know so many layers deeper You're going to have to really Cast about and dig around to find this type of stuff Or that type of thing for that nugget so that nugget may be about politics as it relates to linguistics But you won't find it because it hasn't been indexed and cataloged to that level of specificity And if you search for it on google let's say You know, you're going to have to filter through a lot of stuff So per piece comment per piece comment in the chat that doing this is really expensive um How do we get this kind of performance? From a less expensive system and i'm thinking here that If each of us takes nibbles of this and does it ourselves in a way that concords with other people then Or somewhere on the road to doing that, right? Maybe man so well, that's the thing though is and you know, Pete makes the point that the centopic on is one of the most expensive volumes in publishing history But the issue there is After 1952 They stopped What if they had continued on and continued adding things to this and topic on? Either in paper or index card form or something else That then allows you to take I think there were like 470 some odd works in the great books Um Which didn't include the bible although they indexed the bible in that system So it includes those as what those books as well But what if you continued doing that And you can look at so steven pinker doesn't exist in the centopic on But if people had continued indexing those types of works Certainly at least the big public things You know it'd be great to have like You know cune or popper in the 20th century and their system their coverage only went up to I think sigman freud was the last isn't this something that google's knowledge graph does which is denny hillis's old project I don't I don't know that it does it incredibly well And that's the issue is there's Some subjective stuff that gets added in Yeah And then there's also I mean the nice part about the centopic on is the quality level of what you're going to find in there across western history is phenomenal because They limited it to less than 500 works So you get when you look for a topic in there and you find it You're going to find some some of the best stuff ever written But you're not going to find modern stuff. You're not going to find new stuff. You're not going to find Really new on stuff I mean, it's fine that you don't find the pablum that you've Find in the public square of twitter. That's okay. I don't mind missing that kind of fluff But you know the next two levels beyond what the centopic on was that would be really nice But they spent all this money and did all this stuff And then they quit doing it And that's the kind of the vow and it's that it's that issue of yeah, you try this new system And if you quit before you start Revealing the massive gains to be had You know and in a paper era And pre digital they couldn't have But I had they started this on top of con in the late 80s at the birth of the web Boy, man, you would have there would be a company that does something google is not doing And doing it incredibly well And it doesn't look like it's even digitized Yeah, I've a digital ocr pdf copy of the entire enterprise But I and there may be there may be one company That digitized all of it, but it's a subscription service. I think you got to pay for And honestly for the payment versus I'm you can go out on the open market now and find a full set of those books for Maybe 300 bucks For you know, four to five dollars a copy. I think Is the going rate? And it's easier to use the books than it is to use the digital service Yeah, but I always think hey, how much better would it have been if These and essentially it was graduate students were most of the 26 That they were in the 50s and 50s paying probably two dollars an hour for their indexing work If you had kept that up across At least, you know popular literature since then So partly this was a an attribute of you have something Partly this is a tribute of a cheap graduate labor. It's a little bit like deglennad's psych project problem Pete you I don't know to me it's the dichotomy between the concordant search and the subjective search That you find in most book indexes And there we really don't have a search engine Google can intuit a lot with just the concordance word search And pages that other things are linked to But I tend to find when I'm Looking for something that's three layers deeper You don't find it through I don't find the things I want through google search I have to like dig into Not only books, but then the book index to find The paragraph or the sentence that I'm looking Maybe for and that that takes a lot more work and There are some ai tools like research rabbit or elicit They kind of help there And I find those are the ai tools. I think I find more valuable than the chat gpt, which usually just fits back such a generic problem that You know It's unhelpful altogether except at the lowest level of You know Chat assistant Stuff that I you'd send to a crm system. Maybe Yeah, it's funny. You know what you're basically describing like the entire slash science of like Library science right that's what you've just described Is the the problem that library scientists attempt to solve And even when it's not toxicographers and a bunch of other trades too ontologists. Yeah Yeah, or even um Because you can even look at things from a You know Not just even the large language model side, but um You know, there are some much more very specific branches of linguistics that look at broad language patterns And what falls out of them when you can look at all the words ever spoken in the language And what that could produce versus You know, it's the difference between a close reading of a text and a what's called a distant reading of a text Chris, why are you not an academic wearing a tweed jacket with elbow patches and smoking a pipe? Ah It's the money. It's the filthy lucre or it's um That the other issue too is I Left college and went into businesses and other stuff and then It's now Academia is so hard to get into now Even to go back to it Um, I had a friend who died 2015 2016 he what he had reached the highest rank of professor one could at the university of southern california And I think when he died he was making almost He was he was making a salary of over 200 000 from the university In addition to other consulting fees that went way higher beyond that um When he died The they took the named professorship Drop the salary And then went out and hired 10 10 other faculty With that same money. Wow And so to be even to be a faculty member You know you're you're it's there's just almost no money in it and then Only a portion of your time is actual research.  I love that Um, yeah, thank you. I I was that was a curiosity and boy that I pulled on that thread and it turned into a Sweater on the floor. It's good And it's interesting how many different I mean, it's fun to delve into but it's all yeah It's interesting how many different and groups and tech people are trying to make sense of the world including llms, right? Because what we're doing right now is we're feeding the corpus of everything into these neural nets and and helping shake them until they represent What's connected to what? Yeah, I but generally we're doing it too without There are a lot of research groups That are looking at the history of all these problems and Most of them are incredibly well delineated Kind of what has worked and what hasn't in the past and then it's okay now you have this massive computing power and search power How do you leverage that against those pre-existing problems? and I When I look at most of the space most of the technologists Even some of the academics who are in the space Are totally ignoring everything that came before and it's like let's start from ground zero And I for the life of me. I can't figure out why they Would want to do that um I'm you know, maybe computing power is just so big and so cheap that They'll get to the same place almost as fast as they would have otherwise, but I have to Suspect that that's not the case Although jimson. The mining is on the case on that one and Although I have come to the realization recently too that um I always fault van of our bush For holding us back Because he never mentioned things like the commonplace book in his original essay But apparently as a broad category van of our bush If he could get away without siding any prior work in any area he would And it was literally a career long thing for him that he did that And it made it much easier that given his position as a dean And a senior scientist in the united states during the war He could get away with it In ways that if you were an academic today, you probably unless you just were doing military Rated engineering research and you weren't publishing except internal to the government with clearance You wouldn't do that anyway, so And that you know, and then there's like guys like whole outlet who worked for decades with government money Out in the open in the public But it really wasn't until the later You know 70s 1980s That people really discovered and saw his work and then it's like oh that looks like the internet now instead of We're making the internet now and let's look at what happened before And see if we can't mimic And use the solve problems that they solved 40 years ago To recreate that thing now So the internet recreated Almost whole cloth what he had Done in the you know teens 20s and 30s But just with a lot more people These people would have enjoyed being alive today today, I think Or in the in the late 80s certainly that you know would have worked out pretty well Cool Um, we've kind of gone through our hour Shall we fold this pub tent for the day? Let's do it. Yeah, let that firm in for a while and come back with more questions. Yeah. Thank you. Thank you. Yeah Or if you figure out the the hug the solution between the bridging the gap between concordant search and creating a


All righty, welcome back to Operating Systems. So today we get to talk about centiphores and not the fun flag ones that you have to signal ships with. So first we learned about locks already. So locks ensure mutual exclusion, AKA only a single thread can execute at a given time. And we had this because we wanted to prevent data races. So that critical section, so that piece of code between the lock and the unlock call, well, only one thread at a time, that's great. But it doesn't help us that much if we want to ensure some type of ordering between threads. So we might want to coordinate a little bit. So how do we ensure ordering between threads? So let's look at this problem. So you have one thread that just prints this as first and another thread that is going to print I'm going second and ideally you want to have them always print in that order guaranteed. So let's look at the code. So here we are, our main thread we create two threads. We create one thread that wants to execute print first and another thread to execute print second and then afterwards we join them. So above here in print first we just print this as first and print second, we print this as second. Our goal is to always make them print in that order. So does this work initially? Well, let's see. So hey, it worked, we're good. Print first, the first one printed first and the second one printed second. Oh no, we have broken it by running it, what, three times? So that's not good. So do we know how to fix this? Is there any way I could make this always print this as first and this as second guaranteed with what we know already? Yep, give the first thread a lock. So I should create a lock. So I have a lock. What do you want me to do with it? Then unlock after the print. In the second thread I can join the first thread. So right now in the second thread I can't access this array from main. So only start after the other thread finishes. So how would I do that? Well, first let's execute this locking solution. So I'm going second, first, second, and didn't seem to do much. Yep, sorry. Join after the first thread create. So just do a shwoop-de-doop? That, will that work? Yeah, this is the same as executing them sequentially, but it should work right first. Always going to print this as first because, well, our problem was we created two threads. The OS could have scheduled whatever one to run first, whatever one to run second. We have no say in the matter. In this case, we are creating two thread or we're just creating the thread and then waiting for it to finish, then creating a thread, waiting for it to finish, essentially making it sequential but it's going to always work and that's about the best we can do now. Yeah, that's about the best we can do and I guess it works for this case but it might be that there's just a bunch of other stuff like, oh no, useful. Assume that this is some useful code after the prints and we just want the prints to happen in order and then both the threads to execute in parallel. So your solution works for the prints but doesn't get us quite where we want to get if we have a more complicated program. All right, what about hacking this lock? That was a good idea. Can I hack it a bit more? So, at this point, if I just call unlock, unlock doesn't do anything but let's do something fun. What about if in print second, I try and get the lock and I have print first, eventually unlock it so I'll just grab the key and then I'll just try and get it again. So, I'll grab the key and then wait for print first to execute, print this as first, then it unlocks it and then I can lock it again. Would that work? I see some confused looks. So, I'll have the case that if print second goes first for some reason, it just essentially grabs the key, locks it and then it's trying to call lock again. It can't do it because it has the key. It's not allowed to go. Then if eventually print first will run, print off this as first. So, print second didn't happen and then unlock it, which would make the second thread be able to pass through this line and get the lock and then print this as second. Yeah. Well, I need a second unlock in this case here so I can just have, do that, yeah. So, the first thread runs first and unlocks it even though it's not locked, that's fine. It just doesn't do anything. That's not super fine, but let's see. Oh, that was a fluke, don't worry about that. It was just running, thinking really hard. I'm not thinking really hard. There, worked. So, it technically works because it never prints second before first. Sometimes it just doesn't print second and it's your problem. You just need to restart it again. See, it didn't work, it worked, yeah, fine. So, this kind of works. It was an awful idea because, well, it kind of works if the second thread goes first, but if the first thread goes first, well, it'll unlocked an already unlocked lock so it won't do anything. And then the second thread will lock it, it'll acquire the key, and then it will call lock again and it can't pass because it has the key. Nothing else is going to unlock it at that point because thread one's done. So, it will sit there forever waiting and, well, that's like a very lame version of something called a dead lock. So, we all get that, that's kind of a bad solution. So, this is also full of undefined behavior so if you technically read the documentation of a mutex, what I did here, this unlock in the first thread, technically you are only allowed to unlock from the thread that acquired the lock. So, technically that's not allowed even though it kind of works sometimes. So, technically I should not be calling unlock while I do not have a lock. That is undefined behavior, that is no good. So, yep, no, so if the second thread executes first and makes it and calls lock, that lock currently isn't held by any thread like the key's still available. So, it would grab the lock and then, well, it can't pass this lock call. So, it can pass one but it can't pass the other. So, the first lock, essentially we used it to prevent, so in the case that, yeah, so we used the first lock to prevent it from going any further. So, we essentially grab the lock so that this lock will stop it from making any progress until it gets unlocked by the other thread. So, that's why we had two in a row here. But this is a bad idea. All right, it kind of works so. Like, it technically works which is the best kind of work. Print second never happens before print first, that sometimes print second never happens. It's like, was that malicious compliance or something like that? So, the locking idea was also good so you have to be able to differentiate while when you need mutual exclusion versus when you need some ordering. So, for example, if this was our print first so say it was implemented in this silly way, this would not be considered thread safe because if we execute this and they're all different system calls, well, we're gonna get, sometimes we get it in a correct order that makes sense. Sometimes we get it in like just weird orders. So, this I'm going second is first. What? So, if I wanted to make this safe and make sure I get a line at a time, that's where I would use my mutual exclusion and my locks to make sure that, well, if we set up a mutex, we'll make sure that if print first grabs a lock it does all three of those right system calls in a row without getting interrupted and without switching back and forth and similarly in print second. So, if we wanted to fix that with the mutex then we could create a mutex, make sure we lock it and then if we lock it while only one of these is going to execute at a time because now we have mutual exclusion. So, if this thread gets a lock, well, it prints all of these in a row, we will get the whole line and then if the second thread gets a lock it prints all those in a line in which case this will be like little print, I'm going first, I'm going second. We don't know what order they're in of course but we don't have the case where the line split or something weird like that. So, that's a new consideration for you whenever you call functions. So, in the documentation you will see that some functions declare themselves as thread safe. So, if they're thread safe that means you can call them with a thread and it won't mess up the value or be in like some partial order or something like that. So, luckily for you malloc is thread safe so you can call it with multiple threads and it guarantees it doesn't have any data races or anything like that. So, that will be a fun thing because now libraries might have internal data races if you don't look at it and they're not safe to use with threads and yeah, it makes your life very much, very much more difficult if that is a thing. All right, so we're good on this. Mutual exclusion, save that, yep, yep. Yeah, so we have an idea. Can I just make a global variable that I guess would have to be operated atomically that just has some value I wait for and I check to make sure that does that? Well, today's title of the lecture is a center four and you essentially just described one. So, that is what we will figure out how to use today. It is already invented and we can take advantage of it. So, center fours are used for signaling between processes so this unfortunately is an overloaded worm. This does not mean your signals which are like interrupts. This is just like used for signaling like the English word notifying someone of something. So, center fours are basically just an integer, an unsigned integer that is shared between all threads and optionally you can use a center four to share between processes if you really want and then you can have some ordering between processes if they need to communicate. So, think of the value of a center four as just an unsigned integer. So, it's going to be zero or greater and it only has two fundamental operations. They might be called different things based off some literature you read but the names of the library and the names I like to you is weight. So, all weight does is it decrements that value atomically and post increments that value atomically and the only rule here that makes this useful is weight will not return until that value is greater than zero. So, make sure that that number can never go negative. So, if you call weight and it wants to decrement the number and the number is currently zero, it won't do it until some other thread increments that number and then if it increments that number from zero to one then you can decrement it from one to zero. So, initially we can set that the initial value of the center four to whatever you want and basically that is how many the number of weight calls that may occur without any post calls. So, that many threads could run in parallel as long as we don't have any post calls. So, the API looks a lot similar to pthreadlock. So, it's its own header file. So, it's center four dot h and it's called SEMA init. You have to initialize it. There's a destroy and then there is a weight. So, that's the decrement and if it's zero it will just block until that value has been incremented by another thread and then there is a try weight which is the non-blocking version of that. So, it will tell you whether or not it decremented successfully and then post just increments. You shouldn't have to check the value for that because it should always work and all these functions just return zero on success. You might notice here in the init there is this pshared. So, it's a boolean. If you set to one it will be shared in any other process you fork in shared memory. So, that's how you can share it between forks by default. If you set this second argument as zero that means when you fork it will get a new end up the new process will get a new independent copy of it. It won't be shared between the processes. So, let's see how we solve our problem now. So, we're going to make sure that one thread always prints first. So, let us go back. Whoops. So, let's get rid of our poor, well not our poor idea but like the way I used it, probably not great. Whoops. Yeah, sure. So, let us declare a center for. Mf4, set. So, let's create one as a global variable and then in main we will initialize it. So, sem init, it's called sem will shared. Hmm, my initial value should I set it to. Hmm. Yep, all right, zero. Let's set it to zero. So, if I want print second to always go second, well I should probably do something like sem wait, right? So, that should decrement it. It's currently zero, well yeah, it's current value is zero. So, if the second thread gets scheduled first what happens when it gets to wait? It should block, right? Because the current value is zero. So, if the current value is zero it's going to wait for that value to be greater than zero. So, if I want this to proceed I probably need a post. Where should I put my post? Yeah, after the print in the first thread, right? So, sem, something like that. So, should this always work? So, let's argue about it. So, if the second thread executes first, well it will hit sem wait and it will have to block because the current value would be zero, right? Okay, so it can't make progress, it's stuck there. Even if we gave it all the time in the world can't reach that print line. So, then that means the first thread would execute first and print this is first. There's nothing stopping it from doing that and then it's going to change the value of that center four from a zero to a one and finish or do whatever and then this thread can now proceed. So, it can now change that value from a one to a zero and then print its line and it's done. So, that should work if the first thread goes first or sorry, if the second thread goes first. What happens if the first thread goes first? Well, it's going to just print immediately and then change that value from a zero to a one and then the second thread would execute and it doesn't really have to block that long it just has to decrement it, it's just one to zero and then it prints. So, in both cases I should get the order I want. So, let's see if we fixed it. First, wow, look at that, we fixed it we fixed it and I don't want to sit here and run it 10 billion times because we argued about it. We came up with all possibilities that might happen which in this case thankfully it's two and we can see that, hey, has to be in that order no matter what because of that wake call. So, we all agree with that, that works? Yeah, no, you can only use the API to access it it just keeps track of that value internally you just initialize it to some value. So, you created it. Yeah, yep, it could. So, what was the first question, sorry? Yeah, so this is, well the first thing we know to ensure ordering there's other ways if it gets more complicated we'll see next lecture but this is one of the ways, yeah. Yeah, so that's another way, like a seven four just a value you can declare it just like mutexes I can create multiple of them if I want. So, yeah, if it gets really complicated I just have separate ones for different tasks probably a lot easier to read. All right, so this worked and we're all good on it. All right, here I will make a subtle change. Watch, I can break your code with just changing one number. Does this work now? No, why? Yeah, the second thread, well it can just go past the weight change this from a one to zero, no problem. I don't, I broke it. So, that kind of sucks because the correctness of it depends on this initial value I just can't read the weight and the post calls because guess what, the initial value really matters. So, it kind of gets like a pain like that. So, do do do. Oh, yep. So, how is this any different than using join and bearing cereal? Whoops. Oh yeah, and there's a question can you order three threads like this and you sure can, yeah. We can order as many threads as we want. So yeah, the nice thing about this is, say, long calc, long calc. So, we can still get the order between the threads but those calculations could actually run in parallel. So, say the first thread prints, this is first post it and then does a little bit of work before it gets context switched. Well, then it would come to the second one, print it off and then it could work at the same time and switch back between them over and over again or they could run in parallel. Yeah, so with just joining, you have to wait until a thread is completely done, you can't just wait for it to do a little thing or make sure that only one runs at a time or whatever they're just pure parallelism if you can just go, go, go, go. For this, we need to prevent data races so that's where mutex came in and then this just lets you have some ordering between the threads without them finishing all the way, which might be useful. Yeah, sorry? No, if it hits some weight, it blocks until the other thread goes. So, the only part that is kind of serial is that the second thread will wait until this print happens, that's it. But after that, they could run in parallel, you could context switch between them, they could both make progress at the same time. Just initially, if we start executing print second, it's gonna have to wait until print first does its one print line and that's it. And then after that, it's full, go in parallel. Yeah, yeah, if I had a third thread that was waiting, it's just like mutex lock, you don't know which one. Ideally, there'd be some order, so it depends on the implementation. Ideally, they'd be in the same order they tried to wait on, but I'd have to double check the implementation, but it should be fair. Then also, if you initialize to one, can you wait? Yeah, so let's fix it. So, if I initialize it to one, well, here, I fixed it, I can wait twice. So, in this case, it would, yeah, this should work, right? If I initialize the initial value to one, should work, I just have to argue about it. In different ways. So, this weight, well, it could go from one to zero and then get blocked here until it goes from zero to one from this, or I might have the weird situation where this posts first, so it goes from one to two and then this would bring it from two to one and this would bring it from one to zero. So, generally, you don't wanna do that because I just added another weight call instead of just setting the value to what I probably should have had at that, which I still do. All right, so we're pretty good at center fours. We can do something way more complicated now, right? All right. Oh, so what's the reason for letting us pick a value? Yeah, so, well, let's get into it. So, here's what happened. So, we answered the question at the bottom that was just basically what happened if we initialized the value to one, stopped it from working, unless we add another weight call and we fix it. So, this kind of looks familiar. So, our center four is kind of like mutexes. Like, can I use a center four as a mutex? Yes, how? Yeah, changing from zero to one and one to zero is kind of like locking and unlocking. So, which one's which? Yeah, here. Yeah, one to zero is locked, zero to one is unlocked, right? So, that means I could use that and if the initial value of the center four is one and I use it like that, that lock and unlock. So, I use weight for lock and post for unlock and I always pair them. Works exactly like a center, or works exactly like a mutex. So, a mutex is actually just a special, just a constrained version of a center four that's a lot easier to use. Because, well, you can kind of more easily screw up a center four than a mutex because a mutex will just kind of stop working. So, here's how to use it as a mutex and note the value. So, if we tried to fix that counter example before, well, I can just summon it there, make sure that's initial value is one and then for lock, I use weight and for unlock, I use post. Again, this example is kind of silly because, well, if I really wanted to, I could just post the center four like 80,000 times and maybe I can read the value if I can just hack into the thing or whatever, but basically this just works as a center four. Or sorry, it works as a mutex. So, let us get into the hard problem of today. So, yeah, so also that was one reason for letting you pick the value because, hey, you might want to use it as a mutex if you really want. So, let's come up with a solution for this problem. So, this is real fun. So, assume you have a circular buffer. What's that fancy word for an array that if it goes out of bounds, it just restarts at the beginning. So, if I'm at the last element and I go to the next element, well, it'll just bring me back to the beginning. So, if there's n things in it, the index at n minus one is the last. If I go to the next one, it should bring me back to zero. So, we have multiple threads that are multiple producer threads and multiple consumer threads, which that's a lot of concurrency, which will be fun. So, we have a few rules here. A producer should write to the buffer. So, they should be filling things into it. And a consumer should be reading from the buffer and consuming that data. And there should be a few rules here. So, these are all like data in an index or in a big array. So, a producer should only write to the buffer if that slot is not already filled with data because otherwise we would be overwriting data that hasn't been handled yet. And we'd be losing some information. So, we don't want that to happen. And a consumer should also not read from a buffer that's empty because there's nothing in it that's a waste that should only read valid data. So, I set this up so my code, all the consumers share an index and all the producers share an index and I don't have any data races with trying to access the next element or anything like that. So, you can assume no data races in between the producers and the consumers, but these rules are not fixed there. We have to fix those rules. So, let's see the code. Producer consumer. All right. So, here's the code. There's some space to initialize some center for us and just don't worry about the while conditions or anything. Just think what the producers are doing. So, each producer thread will simulate doing some work and then it will try and fill one of those slots. So, I can have any number of producer threads that all try and fill a slot right now. There's no coordination between producers and consumers. All the consumer will do is try to empty a slot and that's it. And then simulate doing some work on that data. So, if I just have this and I try to run it, producer consumer, let's say I have 10 threads of each that generate 15 that are generating 15 pieces of data and I run that all I can see some issues. I have it printing a red line every time we do something bad. So, we can see initially we were trying to empty slot zero. So, initially the array is completely zero. So, we tried to empty slot zero, but it's already empty. So, we read some invalid data or just read no data. So, that's not good. Then it went on and on and on again. And then all my, it looks like all my consumer thread stopped and then, well, all my producer threads started. So, it filled slot zero, one, two, no problem. And then the other, the consumer came empty, what, five slots and then the producer filled up another five slots. So, it kind of worked. So, let's see. So, when I run this to the integer arguments are the number of producers and the number of consumers. So, I can change this a bit to have more producers than consumers. So, I can see some more interesting things. So, if I do that, I can see that, well, initially my consumers run, they each try to empty a slot that is already emptied. So, that's not good. Then I fill all the slots, I empty some more. So, now these ones are filled and now I start filling slots again. So, now I'm in the situation where I'm filling a slot that has already been filled. So, no producer or sorry, no consumer has read the data at zero yet. So, I get both errors now, which is not fun. So, if I want to fix this, this is an ordering problem. So, I should probably use centerfors, especially considering I created something called initialized centerfors. So, what, any ideas with what I should do here? Yeah. So, don't worry about the loop bounds. I basically use centerfors to produce, to count the number of things I need to produce in each thread. But, yeah, so I'm using some centerfors myself just to ensure some type of, just for producing the data, because I want it bounded, I want it to go on forever. So, yeah, don't worry about the while loops. Yeah, two centerfors, one for read, one for write, yeah, same thing. So, I should wait in a consumer? Okay, so, with centerfors typically, it's easiest just to do it one step at a time. So, usually placing the wait is the first thing. So, in this case, I want to prevent, I want to prevent reading a slot that has no data in it. So, my consumer needs to wait. So, it needs to wait on centerfors, let's give it a name. So, I will call it, what's a good name for it? Sure, filled slots. So, I'll keep, I'll basically make sure that there is at least a filled slot. So, if I call it filled slots, and get rid of that compiler warning, let's initialize it. So, initialized filled slots to what? Yeah, the size of the buffer, which is what I call it. Now, buffer size is up there, buffer size. Like that, yeah. Oh, we're getting a fight, zero, yeah, zero. So, let's see, if it was buffer size, and we have a wait on it, let's see, wait on filled slots here. So, if initially the value is buffer size, so say it's 10, well, we'll wait, and they'll go from 10 to nine, and then this thread could run first, right? So, we'd be reading a slot with no information in it. So, yeah, yep. So, in this, because they are in lockstep with each other, and I don't have any data races between all my producers and between all my consumers, it's fine because they always access it in the same order. So, as long as I'm making sure I obey the rules, I won't have an issue, because, well, if there's one slot that is filled, it's going to be slot zero first, and then I'm going to consume slot zero first, and it's always going to be in a row, and I wrote it so it doesn't have any data races, but yeah, if I didn't give you that like fill slot code that doesn't have a data race in, then yeah, you might have more problems, but because I access it in the same order in both, I don't have that issue. Okay, so, where'd we get? We got our weight here. We said that it should initially be zero, right? So, if that zero, that seems to mean that if a consumer thread runs first, it will hit this weight, and if its current value is zero, it doesn't do anything, right? It needs to wait for at least one producer to go. So, where should I do a post if I want this to go? Yep. After I fill a slot, right? You agree? Thumbs up, we're all good. So, I should do some post. So, this should work, so this will just wait and say there's like all 10 consumer threads just get stuck at that weight. Well, if I produce like up to 10 things or however many number of things, well, I would post this all the way up from zero to 10 and then 10 consumers could all go at once, which is fine. Yep. Yeah, so the question is, hey, can I go back and produce like, it's kind of overwrite a slot? So, that's also part of the fill slot, so I make sure in fill slot I don't overwrite something as long as we're playing nice between things. So, yeah. Yeah, if I try and overfill a slot that's already filled, I will get an error. Well, yeah, there, that's a good thought. So, do I also need to keep track of the number of empty slots so I don't overwrite an empty slot? Probably a good idea, right? Because even though internally it's consistent, it might be between the threads. If I don't pay attention, well, they might overrun each other and eventually you will get out of sync and you will start filling already filled slots, which is bad, because let's see. If I run it right now, yeah, I see I get a problem where I am emptying a slot that is already empty. So, essentially my, let's see. So, I emptied a slot, so yeah. I filled some slots and then my consumers weren't fast enough and got over it. So, I need another center for to make sure that I do not empty slots that are already empty. So, let's create another center for to keep track of the number of empty slots. So, here, my empty slots, is this good? Yeah. Yeah, my initial value should be 10 or I guess more abstractly my buffer size. And then here I need to make sure that while some weight on an empty slot, I call it empty slots. So, this way I could fill up to 10 of them. So, I can fill up to 10 of them because I'm making sure I have an empty slot. Otherwise, like I said before with the fill slot, it just keeps on going. So, yeah, it would overwrite that. So, make sure that I have an empty slot. Initially, I can fill up all 10 of them. So, the entire size of the buffer. And then I probably need a post here, right? So, whenever I empty a slot, then I have a new empty slot. So, does that work?  So, we filled a slot, boom, immediately it got consumed. Then we filled what is that? Six more slots, then emptied slot one and then filled slot seven because while that's still eligible, then we empty slot three, then we fill slot eight, nine and we could fill slot zero, one and two because they've been emptied already. And, oh, look at that. The consumer goes empty slot three, fill slot three. So, as soon as it's done, as soon as it's empty, we go in, we put some more data in it. Empty slot four, boom, fill some data, empty slot five because we've now generated all of our data. Empty slot five, six, seven, eight, nine, zero, one, two, three, four, boom, we're done. That's all 15 elements. So, even if I do the other way around where I have more consumers than producers, well, basically what's going to happen is as soon as the slot gets filled since I have more consumer threads, it's pretty much immediately going to be emptied. So, fill slot zero, empty, fill slot one, two, emptied, fill slot three, four, emptied, that works, right? Yeah. So, if we don't use the empty slots, what happens is we're essentially not constraining the fill slot. So, this fill slot function will always, the way it's written in is guaranteed to always go from zero, one, two, three, and then if it makes it to nine, it goes back to zero, but it won't check if zero is filled already or anything like that, right? So, it always goes in the, fill slot always goes in the same order, but can leapfrog ahead of the empty, the consumer threads that are trying to empty if I don't have this, right? So, let's see, if I run this other way around. So, in this case, it says slots already empty because, well, I, my producer thread, I had two main producer threads and it was filling slots and it essentially overwrote, oh, it did overwrite, it should have overwritten. Yeah, so slot is already filled. So, it overwrote two and then it leapfrog, and then those are just gone. So, I lost them. So, now I'm going to have slots already empty. Yeah, so in this case, I'd started losing information when I started filling and I started filling slots that haven't been emptied yet because I just keep on going with this without that empty slot center for, I just keep on going as fast as I can. I don't care if I overwrite anything. All right, we're good. Yeah. So, why the initial value of empty slots is buffer size and why do we have zero for filled? So, yeah, easiest one to argue about is filled because, well, oops. One problem is we essentially don't want to empty a slot until it's been filled at least once, right? And initially it's all empty. So, the first thing we wanna do is prevent any consumer thread. If it runs first, we don't want it to do empty slot, right? And we would put a weight in front of it and the only way it's going to wait because remember, weight will wait until that value is greater than zero. So, the only choice we have is to set it to zero to here so that a consumer thread gets blocked. So, that's why it's zero for this one because otherwise if we set it to one, then a consumer thread could just run immediately and it would empty an already empty slot. And then for the empty slot, why we set the buffer size is we don't want this producer to essentially overwrite slots that already has even if you say we have like 15 producer threads, we don't want each of them to execute once otherwise we'd be like overwriting, we'd write 10 elements and then we'd overwrite five, right? So, we can only at most fill up that entire buffer full of elements. So, that's why here that buffer like we could have at most initially buffer size number of producer threads because each one of them fills in one slot. So, if it's size 10, we can fill in 10 things. So, that prevents us from essentially overwriting information that hasn't been read yet. Okay, we're good because that's like, that's a pretty complicated example. All right, cool. Let's quickly wrap up then and I'll be around. So, yeah, here's doing that problem. So, first I kept track of the number of empty slots. So, up to buffer size and then made sure that consumers never consume empty slots and that was keeping track of the number of filled slots which is initially zero. So, all that's in your slides and yeah, if we initialize both, what happens if we initialize both of our center ports here to zero? Yeah, yeah, it's not gonna do anything. Same thing? Same thing? Yeah, if both the initial, or both the initial values are zero, well, if a producer runs first, well, it needs to wait on empty slot. It's currently zero, so it'll get blocked. Doesn't matter how many I have. If I have 10 of them or 20 of them, it doesn't matter. Then for consumer, well, if the initial value is zero, guess what? It just blocks here as well. So, all my producer threads get blocked, all my consumer threads get blocked and nothing does anything. So, your initial values are pretty important.  We use center fours and sure proper order. Okay, we're over time, bye. All right. Just a reminder, point for you. We're on this together.