My code
https://github.com/suspectedoceano/dining_philosophers.git
My medium article
https://medium.com/@jalal92/the-dining-philosophers-7157cc05315
Mentioned sources
~https://www.codequoi.com/en/threads-mutexes-and-concurrent-programming-in-c/
~https://youtu.be/UGQsvVKwe90?si=GEbywvMHRGV11F8u from @jamshidbekergashev6746
Philo visualizer
https://nafuka11.github.io/philosophers-visualizer/
Timestamps
00:00:00 Important intro 🚨
00:05:52 start to code
00:21:34 Parsing the input
00:35:06 Data init
00:57:02 Dinner simulation
Let’s create the biggest coders community!
typedef struct 🔗s_links🔗
{
👨🏻🏫 My FREE Udemy course for total beginners, pre_knowledge before C (Overflow, 2’s complement, BASH, VIM…) – https://www.udemy.com/course/oceano_0b0001/?referralCode=C218698D6A3E3D16EEEB
📑 Notion community page (free coding sources piscine, cursus) – https://suspectedoceano.notion.site/Ocean-s-42-fd42e3ed0f6049ca98fb3b290b84d4d0?pvs=4
🧾 Medium (code articles) – https://medium.com/@jalal92
📲 Telegram group – https://t.me/suspectedoceanO
💻 GitHub – https://github.com/suspectedoceano
🛸 Discord – https://discord.gg/hkUvRaDcEP
🐦 Twitter – https://twitter.com/SuspectedOceano
☕️ ChannelSupport – https://www.buymeacoffee.com/suspectedoceano (if you read this, you are already supporting, TY!)
} 🔗t_links🔗
Hello friends this is me from the future before starting I would like to give you some interesting sources in my opinion to take hold the problem because I realized that while I’m en coding I don’t go too much into details so the first thing is this medium article that
I wrote about the ding philosophers it contains the functions that uh I used uh in my code for example the precise Us lip and other things basically I go into the details you can read this if you want to dig down if you have any doubts
Basically these are my notes the notes I took before tickling the dining philosopher so you can have a check there is also a video here so this is all the theory I needed to to code this thing of course I have another article uh related to Deadlocks again with the
Video the deadlock is the gist of this learning philosopher you need to avoid this so irra wrote as well my notes with some um code to test and that’s it then I would like to mention this blog by miao sorry for pronunciation miao excuse and this blog is really amazing
Especially for Threads mutexes and current programming Inc but generally speaking it is a very good source for for the choose school projects C programming and computer science in general so kudos to Mia amazing Source highly highly suggested especially this one for the dining philosophers then there is also this video here uh
From Good Luck where are you from my friend Russia Bulgarian it seems this is a good video which gave me a go to the project so thank you very much I suggest the guy follow him legit then apart from sources to take the dining philosophers
I wanted to talk to you about a little notion page that I’m doing on the spare time in which I basically put all the sources I’m using I found online this is a public page right this is a public page that everyone can modify everyone can basically put its own links here its
Own stuff the sources used to do projects and so on not only from school fortu related to C programming to Vim to Shell whatever related to computer science because I have a lot of people following me not only from school 42 I know a lot of people follow me from Axl
School which is an African School basically it’s a school 42 for Africa as I understand so what’s the gist of this ocean 42 doing that we can create a big big repository that everyone can use and everyone can exploit to find sources good quality sources right because the
Thing is that it’s very tricky to find good sources in my opinion uh I mean I get a lot of views from it Channel which initially was thought only for me to train myself and allegedly a lot of people requ requires these videos so here it would be marvelous if we can uh
Collect a lot of creators making video blocks and so on related to coding and they can all share their own page get exposure this is not a snake oil link like Link in the description I want to get the fee from ads no this is not this
Is just a bbal notion public page I don’t sell anything this is just nothing it’s just a a project that we can do all together because we all have the same problem we want to learn how to code for free so we can crack the code Al together going into the detail for
Example um there is a already a girl that made uh a very amazing uh lesson for beginners here variables and functions it is in French the girl is French Elsa salute Elsa and basically is this ebook frankly uh very well done for beginners in the C program language which is freely
Available everyone can can read can use and I think this is sick if we get a lot of creators sharing stuff in this notion page we can have a really a marvelous repository in which everyone can fetch something give something giving something you will get exposure eventually if this becomes a thing so
It’s a positive sum game win-win everyone wins you share your stuff you get followers you can say you’re cool you increase your subs in get up and everyone is happy of course please don’t spam there is plenty of snake oil sellers in YouTube and in internet in
General so in this page there will be garbage collection not likey this will be like Java here keeping with the team of creators uh sharing stuff I highly suggest to you uh another simple name Thon out thono I don’t know sorry for pronunciation she made an amazing um tutorial for push swap explained
Masterfully much better than me so I’ll suggest to follow the girl and prompt her to make more videos because she is really good at tldr would be we can create a big community of Learners we share stuff and everyone wins we learn to code for free just for fun so that’s
It for this boring introduction I hope my ding philosopher solution is correct 100% correct it works but I’m not sure that’s the real correct thing so we’re going to do this together please comments and if you want here’s the community you have the link to the
Actual Discord and you can uh call me the server and tell me hey your solution is really bad here’s mine boom and you submit and we all happy to have a better solution thank you very much my friend Hello friends today is going to be the dining philosophers problem this is
Going to be kind of longish I will try to code this from inception to conclusion so you’re going to be able to see how I tackle a problem like that this is the kind of video I’d like to find on YouTube so I’m going to produce myself hopefully this going to be useful
For someone else and yeah let’s just start and inde this is going to be a community work don’t follow me like I know everything I’m just a dude with a mechos coding like you a student like you so there can be mistakes there can be bugs this is just my implementation
We do this together right right in the comments if you see some bugs some performance improvements that we can make and so forth we are together in that is my friend all right let’s start so I initially create my uh directory like always when we do a project filo
And I City into it I will create like always uh another file and in this file we are going to put all the necessary libraries all the necessary finds and so forth all the Gest that we need to resolve this dining philosopher thing so I’m going to include as o.h this for the
Print F function include the standard Library this is going to be for Malo free Unix standard for the right system C but we’re not actually use this because we have the printf more important for the US liip this is an important function for our project that
We are going to use indeed we’re going to use a use liip with steroids because us Leep is not very precise so we need something better include standard bull why not I like to use Bulls and then of course the p tread. h here we have all the functions controlling mutexes and uh
Threads that’s the gist of this simulation right I have mutex init destroy lock unlock these functions and for Threads I have create join the tach then I have also from the system time. H here is useful for the function get time of day get time of day this is basically a chronometer function
It’s useful to get exactly the time uh from a specific uh eok you will see all right these are the others let’s include also limits. H for INT Max we’re going to check our inputs that are not in measured in inmax now we have to model
This problem in such a way that a computer can resolve it a data structure problem so what is the task on end what I’m trying to well the dining philosophers problem as you probably already know is a classic synchronization problem in which we have many threats that wants to access shared
Sources in this case we are talking about Forks so we have this scenario we have in this case five philosophers Five Forks and a bubble of spaghetti every philosopher wants to eat spaghetti and to do that needs two forks right so you immediately see the problem we have
Collision so we cannot have all the philosophers eating simultaneously so we have to orchestrate this accessing to the actual Force so for the data structure part what is a philosopher well a philosopher indeed is a struct that contains some data for example we’re going to have an ID right in this
Case we have ID equal five it is the identifier of the actual philosopher then a pointer to a left Fork a pointer to a Right Fork and the number of meals consumed and other variables right we will see while we are coding so a philosopher is just a struct we are
Going to create two arrays of structs so this is the way by which I model the problem in such a way that the computer can solve it but what is a fork well a fork is a mutex of course so we’re going to have an array of mutexes an array of
Mutexes long story short we’re going to have an array of philosophers which are these uh strs containing member variables data and an array of mutexes that are going to act like Forks in our problem so this is it the problem is modeled in this fashion two arrays let’s
Now create the actual philosopher struct so it’s going to be filo and let’s say struct as filo and let’s start from the member variables we’re going to have an ID as we saw ID then some variables internal variables let’s start from Mills counter this going to be in the
Counter of how many meals the philosopher has eaten a buum to say if the philosopher is full because we can get an input like that F 5 800 200 200 and this last is conditional it’s not mandatory which is the maximum number of meals that the actual philosopher can do
So we’re going to stock all the meals done by the philosopher inside this variable and here uh we have a flag that is going to be turned on if the philosopher has eaten the maximum number of meals okay so we’re going to see this while coding but just to show you that
These member variables are very useful to solve this problem then we’re going to have um a last meal time other very important member barable because this is going to keep track of time P from last meal and this is very important to check if the philosopher has died because we
Are going to have time to die which is the first parameter if the time elapsed between meals is Major then time to Die the philosopher is dead so this is another important variable it’s going to be a long because we’re going to use microsc in our project and of course a
Pointer to the actual Forks which are mutexes now let’s do something I want to create a struct for a fork you will see immediately why so struct struct Fork a fork is going to be a mutex now I want I don’t want to use use this long data
Type bet thread mutex type right so I’m going to use a type def here at the top def be thread mutex type and we call it type mutex like that very short this will make the code more readable and the for is going to be uh mutex of course so
Type mutex and also it’s going to be an ID which is going to be Fork ID this is pretty useful for the bugging this ID because I know exactly uh which Fork the philosopher has taken so let’s do immediately A type da here type Fork of
Course all the times I don’t want to write this so the type da is pretty Endy all right let’s go back in our philosopher and here what do we have we have a pointer to the left fork and a pointer to the Right Fork okay then of
Course crucially uh we are going to have a pad type right pad type which is the thread ID name ail is a thread we’re going to fit this value to be thread create okay so by now this is it by now this our uh philosopher of course we’re
Going to use also your I type def so type def F and by now we are done we have a fill we have a fork we now need a container we need a struct in which we can stock all the data like the number of philosophers the time to die time to
Sleep time to eat so we’re going to create another struct that I call table basically this is a container of all the data and let’s do that um type def struct table type table perfect and inside our table you a good name also would have been here data General data
Global data you do that table just because it recalls like all the simulation here we’re going to put all the uh inputs received at the command line so we’re going to have long filo number number this is the amount of philosophers namely this value long time to die we choose this first parameter
And the pattern is simple time to eat time to sleep okay then along number uh limit mes this is going to be the five in this case right and this variable uh is going to act like a limit or like a flag for example if it is minus one this
Is going to be a flag in the sense that at the level of the command line we don’t have this input okay so this is a bivalent variable both a flag and a value then we’re going to have uh another long which is start simulation this is basically the time
When the simulation is starting this is important because I need time stamps uh from the start of the simulation basically all the philosophers will have time stamps starting from this value then I will have a very important important bu which is end simulation which is triggered when um a filo dies
Or all fos are full so this flag is turned on in these two scenarios then uh there’s going to be of course other data but by now let’s do only Forks basically this is uh the array to all the forks and type Philo andr to all the philosophers now here I want every
Philosopher has access to these um Global quote unquote values so I need a tip table pointer but here I will get the mistake prob the compiler yells at me that it doesn’t know this um type table so we’re going to do that we’re going to Forefront declare this at the very top
And say type def struct type table like that basically this is an IO for compiler I’m telling a I will this table exist don’t worry so I can use inside my philosopher so you see it is kind of recursive I have a table that contains the philosophers the philosophers have a
Pointer to the actual table this will be super handy because when I pass a philosopher basically I have access to all these data so I think we have enough stuff to start our uh simulation so let’s create some Main see let’s start from the main so immediately we include
Our f.h and basically we’re ready to start the main is a tldd of the program indeed uh from Main we should be able to understand the overall project the overall application so int main int argument counter Char star star argument vector and we’re going to start keeping
With the fact that the main is a t a of the application I would say that we’re going to check if the input given at the command line is correct we’re going to kick in the Machinery otherwise we’re going to prompt the user to please feed
Me with a correct prompt how do we do that well the input is something like that right philosophers time to die time to eat time to sleep and potentially number of meals so we can have 1 2 3 four five or six inputs right so I’m
Going to say if five is equal to uh argument C or six is equal to argument counter here we have a correct input correct quote unquote namely we have the correct number of inputs right then we still have to parts and to check if effectively the input is correct but
Nonetheless this is the first filter on the contrary we are sure that the input is wrong so we have to prompt the user the input is wrong okay we’re going to print an error um and here I’m going to immediately create an utils I want to function that is printing an error and
It’s going to exit because I will call this function many many times throughout the code so let’s create our uh u. C so as usual I include uh f h our header and I want a stupid eror function Sprint an error and it’s going to exit so void
Error exit that is taking a a string literal so const chart star error and it’s going to printf the error so s s new line and I want to after that exit with exit failure now I want to customize a little bit this to do that
We are going to um in f.h put some um asky escape sequence to do that I’m just going to ask CH GPT to write write me some asky Escape uh sequences for the printa so this is the result from CH GPT for doing these repetitive things is
Amazing so I get red green yellow blue magenta CN white and there is that everything is bold perfect pretty fast so I can use this in my printf to make it more um cool cooler so let’s go to utils and I’m going to make my uh print
F uh red and then every time I have to reset this is just the way it works reset all the times I copy and I pass in my other file because we need all the prototypes here at the bottom all right Ms so we go back to the main and here we
Simply call error exit with uh wrong input and then maybe we can say new line we can go in a new line we say green here reset to make it the correct correct is we pass this one boom we are okay like that now for the actual M of
The main function first of all we have to declare a table of course uh a table that will contain everything and and if the input turns out to be correct at least number-wise first of all what do we do uh first of all we’re going to
Parse the input uh giving as an input uh a pointer to the table because we have to put inside the table all these values right and of course argument Vector this is going to be a function controlling U errors errors checking filling uh table data like that uh
Second is going to be um data init still uh pointer to the actual table this is going to be uh inting all the actual philosophers maling philosophers maling the forks and so forth so creating the actual thing and third point is going to be um the actual simulation I guess I
Can call it dinner start still um I passed the table by reference you see how cozy it is to have just one struct and if I pass this I have access to everything and then probably is going to be the last function a clean function
Clean at table no El okay so this is the road map first of all we pass the input then we need the data we start the simulation and then we clean when the simulation is finished either uh when um filo is full basically all the filos are
Full or one F died this is when we’re going to reach this clean function otherwise the loop is going to be endless all right we’re going to start by parsing the input so we’re going to create a model a file the de call parsing doc as always
We are going to include f. H and we’re ready to go so we start from the function void bars input that take is an input uh the actual table a pointer to that of course and arv boom let’s start so we understand that we have uh this
Input right basically what I want to do is to take all these parameters which are a in position one AV in position two AV in position three and so forth right I want to take these strings and convert it to actual integers to to actual values doing that I want to control if
The the strings are actual numbers right actual numbers and to know not major than int Max um then we have also to do the controls if uh time stamps time stamps major than 60 milliseconds so we’re going to do all of these controls to do that we’re going to need a function uh
Alpha to um not to integer but to long because I want to control also the int Max so we’re going to create an alpha to Long Function beforeand because we start from here right I’m going to need say say table um p number is equal to Alpha
2 long right so we have to create this Alpha to long we’re going to do immediately so along the alpha to long as an input we have um a string const Char star Str Str like that now given that this is a function that I’m going
To use only inside this model I say static okay it means that this function is useful only here in the parsing model is not going to be used in other models so of course I’m going to declare a long number inside this variable is going to be Stu the actual number that
We’re going to return and of course we have to initialize to zero this is easy to forget and it’s fairly common to me to spend hours to find these stupid bugs because I don’t initialize variables always initialize uh I can do a trick here I can say Str Str is equal to um
Valid input pass this an input s strr now I will explain you what I mean so let’s create immediately valid input this function again is a static it’s going to return me a const Char star valid input and takes as an input a con
Char star s Str so what is the goal of this function what I’m trying to do check for negatives if there are negative numbers uh this doesn’t make any sense so the input is wrong then check if the number is legit right legit I mean I can have
Spaces I can have a plus I can have a 77 and then I can have after that uh some other symbols like that this is a legit number we are going to need skip all the spaces and then we take the 77 this on the contrary is not a legit number
Because it is not all right three I do a check for inmax initially check for INT Max what do I mean here given that this is a string I mean that if someone inputs a string like that which is a number but it is not a legit one it is
Way too big I cannot even St inside long because it’s way way to be so the skill is that I will check for L initially check for L namely in Max is 2 billion for 47 I think or 48 no 47 I guess for INT Max but not the problem not an issue
Here what I want to tell you is that here I have 10 uh charts right 3 six 9 10 so I say if Len major than 10 I’m already sure sure major than inax right this is not a complete uh control because I still have to check for the
Values ranging from this to uh 9 999 9999 999 right I still have this set of numbers to check but anyway this is a f first filter string wise still to check I will do a check in this in uh my Alpha to Long f function okay so why this
Function returns a pointer well the function is going to return a pointer to the actual number for example if I have this number here the function is going to return a pointer to the seven you see so the uh function Alpha to long is going to start processing immediately
From the digit all right we have already cleaned uh our string all right hopefully what I said makes sense now we’re going to see the code so we’re going to need and int l in this we’re going to accumulate the the L of the string and const Char star return or we
Say better number so this is a pointer to the actual number that is going to be processed all right L of course equal to zero all the times don’t forget and uh first thing skip the spaces so I say while is space so I’m going to create an
Do function here here at the top again we’re going to do static bull is space chart C taking a chart and very simply it’s going to return aoan uh and I say C is Major equal than 9 and C is minor equal than 13 or C uh is equal
To 32 understand right what I’m doing here just watch the S key manual you will see all the charts and basically I’m saying from 9 to 133 which is horizontal tab new line vertical tab carage return or 32 which is the space basically what I’m doing is recreating
The function is space you see all this character as simple as that now here we can also do something more we can say static in line basically we’re saying to the compiler a just boost the performance of this treat is not like a normal function but simply quote unquote
Copy past this here right because the thing is that I can simply write this inside the Y Loop right I would argue it’s not as read able as uh writing is space because here if I do while is space at Str Str you see how readable it
Is if I write directly this is super cricky in my opinion so that’s why line functions are useful because are more readable that’s it so what do you want to do uh until uh you have a space well you want to skip so you’re going to increase Str Str so you do pointer
Arithmetic Plus+ Str Str all right now you don’t have any spaces so you say if at Str strr is equal to plus okay it can be so you go on point arithmetic else if at Str strr is equal to minus this is wrong so we’re going to call our
Beautiful function error exit with fit me only positive numbers positive values you sorry okay uh so at this point we can have the symbols then I say if not and here I have to check if the actual chart is um is a digit so we’re
Going to do the same trick as the space I’m going to create a little inline function at the very top so let’s do that static in line uh bull is digit Char C like that and on the same line we’re going to do c major equal we’re
Going to use the charts here zero here we can also use for 48 but is more readable and C minor equal 9 like that right super simple so here I say if not is digit at Str Str error exit the input is not a correct digit okay on the
Contrary it means that we have stumbled upon a digit right so we can say number our pointer right is equal to Str Str this is the return string right the return pointer to the actual uh number okay so Alpha to long is going to receive a pointer to this seven here
Right because we have skipped all of this then the final check do for the the actual l so I simply say while is digit at Str Str Plus+ L and of course I have also to increase here the pointer so while s Str Plus+ you see okay final control I say
If Len major than 10 or exit the value is to and Max is the limit and at the very bottom we’re going to return number okay I think it’s uh fairly simple this valid input right what do you think okay we keep going on with our Alpha too long
And as you can see a lot of work has been done by my valid input that has return me a pointer to the actual string now we simply have to harvest the actual integer value so here I say while is digit at Str Str what do you do number
Is equal to uh number per 10 of course we are in a base 10 uh plus what plus the Char pointed by S Str minus zero Char zero right because this is minus 48 if you want maybe here is clear for example here if I have the Char one
Which is 49 in the aski table right the chart one is 49 I will get 49 minus 48 which is actually one one that’s the integer value that I’m looking for here of course I also have to increase Str Str all the time so the first time I
Will multiply 0 per 10 0 plus 1 for example the next iteration I will have 1 per 10 is going to go on the next next order of magnitude and we keep going on this is the algor to R verse a value from a string then we have to do the
Second control of int Max so if number is Major than in Max again error exit and we copy the string here like that finally we simply return the number convert it to a string converted to an actual long right so that’s basically it for me for my Alpha to Long the big work
Has been done by valid input you can see these are all static functions Sol used inside this model and now we keep going on with the actual Parts input function the one we care the most so now we’re going to take table uh time to die is
Equal to the same pattern right time to die AR Vector in position two now the time stamps here are given in milliseconds right 100 milliseconds milliseconds milliseconds the thing is that the use lip function once microsc so I think that I can do here immediately to ease my life is to
Convert immediately these values in micros seconds how do I do that well microsc are like um kilog mega Giga right we have kilog mega Giga and in the same Vibe we have milliseconds microsc nanc so it is three orders of magnitude smaller a microsc is three orders of
Magnitude smaller than a millisecond so here I think that the scientific notation is pretty handy to do the conversion because here I would do like that per 1,000 to do the conversion but I can do per 1 E3 basically 1 E3 is one with three zeros it’s super easy right
To make conversions uh in order of magnitudes thank to the scientific notation right now we’re going to use that I do the same also for the other values time to die time to eat and time to sleep so argument Vector in position three argument Vector in position four all
Already converted then I have to make a check for 60 millisecs so I do if table time to die is minor than what 60 milliseconds you can write 60 and then convert to microsc with three zeros or you can do 6 E4 like that then the PN is
Self similar right time to die time to eat or table time to sleep minor 64 what do you do you error exit use times temps major and then 60 Ms all right now um the last thing we are going to do is to check if argument
Vector in position uh five is present in this case we’re going to say that U table number limit Ms is equal to Al to long a in position five right else we’re going to use this variable as a flag giving minus one like that boom we have the
Controls uh maybe there is some bug somewhere I don’t know but by now it seems correct and we’re going to run and we’re going to check for potential mistakes the only thing we have to take this function only this function because the other ones are static and put inside
Fi. H in this fashion so we do parsing and we pass it perfect go back to the main and the parts thing is done we can remove that Cho now we pass to data init we have to actually create uh stuff so let’s create another model that I call init doc we of
Course include the Eder field. H and we start our journey uh we do void data in it and as an input we take a pointer to the actual table right and now what we want to do uh let’s go back to f h given the table we have all these values that
Already set right so simulation we’re going to do later the Boolean and simulation we’re going to settle these three we’re going to Mal for the philosophers and simulation we’re going to put false so table and simulation is equal to false the is a very important buol
And we’re going to use a lot then we have table philosophers is equal to what is equal to Malo the number of flows first now every time we call a function like Malo we have always to check the the return value if not never happened
That a Malo me all you tell me but we have to do that so I create a model a doc uh that I call B save functions you will see what I mean uh I’m going to include fi. h module containing rer functions with embedded controls on return what do I mean by
That uh the goal is to create um a very short main code so I don’t want to control the error returning for the function both from the malow but also for the pad functions which are all self similar we’re going to start from the Malo so you can understand what I
Actually want to do so void star save Malo size T byes right so I’m going to do B Star because the Mal is going to return uh a generic pointer aoid pointer and then I’m going to Simply do return is equal to Malo bytes okay and then I do
The control here if null is equal to Red exit error error with the Mal like that on the contrary return red as easy as that so you see this save Mal look is just a wrapper with embedded control so when I will Malo my philosophers I will show
You at this point I will simply call Safe Malo okay see how cleaner becomes the code I do save Malo table number of philosophers so F number boom easy as that now let’s finish our save functions I want to use many more of them for the
Pad API I will show you immed first of all let’s start from mutexes mutex save so there are basically uh four functions that I can use for mutexes which are init destroy lock and unlock okay uh the idea that I have is just to have one simple wer function like that void save
Mutex handle that is taking a pointer to the actual mutex so type mutex mutex and is going to take an operation code uh an operation code that is going to be an enum now I’m going to show you so let’s go back to my f h and at the very top
We’re going to create an enum for mutexes op code for mtic and threads function let’s do that so enum op code and inside we’re going to put everything I can do with a mutex or a thread so lock unlock in it destroy create join detach
So you see I’m going to create a lot of symbolic constants every symbolic constant is going to have a value I think it’s going to start from one or zero I don’t actually record but it’s not important here here I’m going to use a type def again type up code so now I’m
Going to show you how I use this stuff let’s go back to my save functions and here my save M handle is going to take an up code which is going to be a nom and here we simply say if lock is equal to up code you call a specific function
Which is in our case we threat mutex lock with a pointer to the actual mutex like that right the pattern is self similar right so El if unlock is equal to op code you call the actual function pad mutex unlock L sa in it is equal to
Up code you call Pad mutex in it with pass the mutex and the second parameter is attributes but we don’t really need those so it’s going to be and all else if destroy is equal to up code we call P mutex destroy okay with the mutex else
You simply say error exit wrong up code for mutex and all now you may say okay what’s the gist of it why it can be cool to have the save functions well because now I’m going to create an embed control on returns to make this more valuable so
Embed controls or return by status so it’s going to be static void I’m going to call endol mutex error and as an input I receive a status and an up code so type up code up code what is the gist of this function we’re going to check
The return value so if 0 is equal to status you simply return everything is correct now we’re going to understand why so here you can see all the action functions unlock lock in it and destroyed as you can see they are all self similar all these functions will
Return zero if they are correct otherwise we are going to get a narrow value which is this one as you can see all the functions return an aall the value uh is not correct the string is for all of them similar so the thing that we have to do is to handle these
Return status values and print the correct um string error we’re going to basically recreate the P error function that we cannot use in this project and that is not working because these functions as I understand are not going to set the are no Global variable so the
Only thing is to do manually I say if a invol here to use this symbolic constant uh I have first of all to include to my field. H the her no Eder file so include a now so let’s go with logic so I say if aimall is equal to status and lock is
Equal to op code or unlock is equal to op code you call error exit and you pass this string here the value specified by mutex is invalid okay El if a invol is equal to status and in it is equal to op code error exit we got this string this time
Cool else if this time we take this e did loock is equal to status error exit this is kind of tedious but it will be super useful we copy this string here else if e per is equal to status the current thread does not hold the lock on mutex
Else if and Omen this is the classic mistake not enough memory rexit El if bz is equal to status Orit mutex is locked all right so now what’s the gist of it well the thing is that I will uh wrap around my functions here into my end all
Mutex error see function the up code so I will do this for all the functions boom here it comes this is the final result it has been kind of tedious to create but now when I want to use um a function coming from the BET rad API
For example mutex lock mutex unlock in it or destroy I will simply call that I don’t care anymore about potential errors this is going to all be taking Care by this safe mutex andle I will do the same for the threads it is exactly the same pattern so I will just code it
And I will show you the final results so this is going to be the same thing for uh threads I have my save thread handle of course the Prototype of the function is a little different because I have my Petri create function that requires more details for example I have a pointer to
Function as you can see here right the strange pointer function uh signature then data but the idea is exactly the same I have a wrapper function which is this save thread handle that is going to take a pointer to the thread data type a pointer to function a pointer to data a
Pointer to up code and I can call uh create the tach and the tach and join and then all the controls are embedded in the safe thre handle not complicated to understand so I’m going to copy all of these prototypes in my other file here and save save mutex handle like
That so now I can use this function I can basically forget about this model and we raised the level of abstraction of my code so in a very compact way I can use malog and all the functions from the pad API I think this will make
Overall uh the code much more clear all right now let’s go back to the ACT needs and we made a lot of functions save functions so table FS is okay then we do table for Works same save Mal look table um f number but here I just forgot to
Put the size off operator stupid mistake here I know size off type filo per filo number and here I need sides of type Fork per F number cool then I need to init all the actual mutexes all the actual Forks so I’m going to have an iterator the legendary I iterator which
Is uh minus one I like to start by minus one to do this while Plus+ I is minor than table f a number we’re going to finally call my save mutex andle function and we pass as an input table uh Forks in position I I need to
Take the fork I have to pass by reference like that the op code is going to be in it right because we want to init this mutex every time a mutex has to be inited init that’s it you see how clean it is and then we say um table
Forks position I do 4kd is equal to I so every Fork is going to get a specific number this is going to prove uh super useful for the bugging nice then we have to init uh the actual philosopher so I’m going to create a function that I call fil in it
And as an input I give the table all right this again is going to be another function static filler in it static void filler init type table table like that so basically here for every philosopher we have to give an ID Ms counter full and init all this data and of course
Assign the forks so let’s do int I I is equal to minus1 and I say while plus plus I Minner than table f a number here to make the code cleaner we can say typee filo pointer to filo and filo every time in the loop is equal to table
Filos plus I right this is just pointer arithmetic and I simply say fil uh ID is equal to I + one then filo full is equal to false of course then filo last M time we don’t care by now Ms counter is equal to zero then we have a filo table is
Equal to table very easy and filo we have left fork and Right Fork which is important right ID we don’t care so now we need to assign the actual forks and this is a very important step so I’m going to create an doc function that I call assign
Forks uh field and table forks and also I I is basically the position in the table now let’s do that static void assign for Forks it takes us an input a pointer to philosopher then a pointer to the actual forks and in position relative position in the table and now we have to
Understand a very important concept about uh Fork assignment so we have our philosophers right we have this array of structs and our mutexes as well which are the forks when it comes to Fork assignment what do I want to do first of all we have to really be aware that fil
ID is not the relative position in the array right because we start by zero but the first philosopher as 81 this is important to keep in mind let’s see the actual visualization of the assignment so it’s going to be easy for the Right Fork is pretty straightforward right we
Have the position which is actually the position as well of the fork so we can simply assign uh the Right Fork thanks to the position value for the left Fork the thing is more tricky because we are in a table which is a modular object essentially like a clock right a
Circular object so what do we do we’re going to focus our attention to philosopher number five because we can understand the principle here so we’re zoom in and we see that the left Fork of philosopher number five is the zero so what is the operation well it’s pretty
Straightforward right left Fork is equal to the position of the philosopher plus one because it’s the left Fork the number of the philosophers so we going to have 4 + 1 = 5 Mod of 5 zero you see the reminder that’s as silly as that we
Have just to keep in mind that the table is a circular object so we have to use the modular operator so we do this for all the philosophers and we see that we get this that every philosopher has a left and a Right Fork indeed that’s what
We need to uh do our Sim ation given that every philosopher requires two forks to each so let’s do this in code so here immediately you can understand why I used uh a position here which is actually uh the I value of filler in it right because it’s cleaner than every
Time writing F ID minus one right or to write a new variable so we said that uh we need the actual number of philosophers so I’m going to create an internal variable to make the code cleaner that I call F number and F number is going to be equal to F table F
Number so it’s just a way to make the code clearer then we simply do the operation that is so F uh Right Fork is equal to the position right equal to position so very simple is going to be Forks um position right or better here to make it cleaner I can do filo
Position uh F position So Right Fork is equal to Forks in F position and that’s it given that we have to give back a pointer we’re going to use the % as easy as that on the contrary F uh left Fork is going to be different you’re going to
Be Forks in position fi position plus one right in parenthesis modulo F number modulo F number like that and then we use the % all right this is the fork assignment which is not difficult right but here the problem is a potential Deadlock here now I will show you why
Basically a deadlock happens when we have uh multiple threads that are stuck because they’re waiting for a resource to be freed from another thread namely we have a circular waiting thread one is Waiting For Thread two thread Two For Thread three thread three from thread one so we have the circular waiting now
I’m going to show you let’s pretend that every philosopher is going to take the first fork left what is going to happen boom we get that every philosopher takes the fork and is waiting for the right one but it will never free this is a circular waiting this is a deadlock this
Can work this Fork assignment can work if we desynchronize uh the actual Fork taking we can say that if philosopher is is going to wait for x amount of time before actually trying to take the fork so it can work but we are in a random
Arena we don’t want that we want the code to be more robust we want the code to be uh 100% deadlock free so this Fork assignments is not going to be good furthermore uh if you compile with tread sanitize you will get this deadlock problem even though your code can
Actually work so what is the um solution to this deadlock issue well I found online that there are basically two solution one is the Dy St solution in which only one philosopher is taking the fork in reverse the last one is taking the last fork in Reverse or the odd even
Uh solution which is the one I use in my code in which basically uh we have that if you are an odd philosopher you’re going to take uh the first Fork which is going to be the left on the contrary if you even you’re going to take the right
Uh Fork first how does it work well it’s fairly simple right we have all the philosophers that are going to have a first Fork Target and this will create some contention areas as you can see we have uh philosopher one that has contention with philosopher two the same
For four and three in this case when we have odd philosophers we have the five that is kind of the difference dude in the T but this will work why well let’s try a simulation we have that in our first case philosopher number two is going to win the contention with number
One and philosopher number uh four wins the contention with number three so one and three are forced to wait right because they are waiting for uh mutex that is locked boom they stop forcefully number five our case is Idle but it could have taken the the fork number
Zero then we get that number two and number four took the second fork and they can eat they can eat now then they will release the actual Fork they will unlock the forks and now we start again we have again competition we have contention and every philosopher is
Going to try to take the forks but you see that in this way we have constraints we cannot have all the philosophers reach the fork and create a deadlock scenario let’s just watch the uh possible worst case scenario where is going to happen the worst case scenario
Can be this one as you can see we have only one philosopher with two forks and four philosophers are waiting but let’s have a quick replay of what is going on to understand better we have our contention area and the first philosopher is going to win the
Contention with number two then we have that number five takes his own Fork right it doesn’t have contention for that fork initially so so we have number five and number one that are reaching the fork immediately at the same time we have number uh four that wins
Competition with uh number three and at the same time wins competition with number five so that’s the scenario you see in the worst possible case scenario you don’t have a deadlock at least one philosopher is itting so this even not assignment is robust it works is deadlock free now the problem is
Fairness but we will see how to uh solve this issue as well so this is what I’m going to do this will prove that L free okay that’s the main idea hopefully this is clear so one thing that I want to immediately do is to go back to my fill.
H and change the naming I don’t want left Fork Right Fork I just want first fork and second Fork because we’re going to do the odd even assignment and this is cleaner then back to init and we say this is going to be true if the
Philosopher is odd right so if Phil ID model true you’re going to have this Fork assignment namely first of all you take the right and then you take the left which is going to be first Fork second for on the contrary we just copy this is exactly the reverse so very
Easily we’re going to change it to second and first like that all right so uh we manag to assign the forks even not Fork assignment all right I guess we um have almost finished this init file then while we are coding we can add some other uh variables of course but by now
It’s fine we have our philosophers we have Malik we have Malik uh the forks as well we have in it all the forks and every philosopher has a fork assigned so basically we are here we have the model of the problem on the table right is
Ready to be run okay we simply copy data in it in our other file boom and we go back to the main in it is done now it’s time to actually start the dinner dinner start so we’re going to create another model that I call dinner.
C or I include F and here is going to be the actual meat it’s going to be the actual um simulation of the dinner before starting uh the simulation let’s refresh the input the input can be something like that right so I’m going to do if no meals just return namely if
Here I have zero just return you go back to the main we call the clean function done then we have to take care of if only uh one philosopher one F find you do an ad do function let me go back to the main thing which is create create
All uh threads all philosophers which are going to run a specific uh function um create a monitor thread this is going to be a thread that is searching for uh philosophers which are death uh we have to synchronize the beginning the beginning of the simulation because every time you
Call P tread create the philosopher start to run I don’t want that I want every Philo start simultan so we need a a synchron synchronization thing to make all the phos ofer start at the same time then we simply join everyone all right let’s try to code and understand uh and understand
Everything so we do void dinner start and as an input we have a pointer to the table right type table table so immediately I say if Z is equal to uh um table number limit Mills you simply return go back to the main we we are
Finished back to main clean else if one is equal to table number F number um we’re going to do it later to do a doc function to handle one philosopher else well else we have to create all the philosophers so we’re going to call our rapper function safe
Um thread endle we have to pass the address of the trade ID so we do that we need an iterator i i is equal to minus1 and you say while Plus+ I minor than table field number you create all the threads so it’s going to be uh table
Philosophers in position I we’re going to access thread ID and we pass by reference okay so this is a pointer to the thread ID of the I philosopher then we have to pass a pointer to function uh which is going to be dinner simulation here I don’t need a 100% this is
Redundant already when the compiler sees uh a name of a function without the the parenthesis already understands that this is just a pointer to function we’re going to pass as a data the actual philos for itself so fos in position I uh by reference and the up code is going
To be create okay that’s it this is uh a while loop that is going to create all the threads all the philosophers and I repeat to you every time this function is called uh immediately the thread starts running this uh theer simulation function that we still have to do so we
Need a synchronization thing to uh to make all the philosopher Stars starts at the same time all right I would create my um simulation Diner simulation function so the Prototype is clear uh void star gener pointer dinner simulation and as an input I get another generic pointer I
Call data uh so we have to fetch back our philosopher so I’m going to create a variable type fil pointer fil and this pointer is equal to I type cast back to a pointer to philosopher the actual data like that so in this way we manage to
Fetch back our data of course we put a return all here so we said here that we need uh a weight all fos Synchro start so before end I need this synchronization thing and then uh the actual endless loop right the actual endless loop then now we’ll see endless
Loop of the FI so to wait everyone we’re going to do a function that I call weit all threads let’s put to do now we go back uh into fi. H and we put in our uh table another Boolean another Boolean which is all threads ready to Synchro
Philosophers so while we go back to in it all the time we go back here and we put our fals here all threads ready equal fals okay we go back to dinner and what is the thing I’m trying to do uh this function is going to uh take the
Table as an input because contains that variable all threads ready and now we have to understand how to uh engineer the thing if you want uh the thing that we’re going to do is that uh a dinner start after this while loop we’re going to say hey now uh now all threads are
Been made right already right just after the the loop so we can set uh that Boolean all ready to True um the thing is that we are in a multi-ad environment so accessing a shared variable is going to be a race condition so we need to protect this Boolean with a mutex we’re
Going to go back in our uh field H and in our table we’re going to create a mutex we’re going to create a mutex type mutex that I call table mutex avoid races while reading from uh table of course we go back in our init
All the time we have to do that when we create something new and we just init uh these mutex so we do save mutex handle table table mutex and it easy right with my save function control already made so I don’t need to worry about anything
Okay now we have this mutex in the table let’s go back to the dinner and here the idea is that I will lock that mutex set the boan to through and then unlock three lines of code uh this is not not cool this is not cool I don’t want to
Write all this lock and lock everywhere in my um in my project so it’s time to create Getters and Setters to make the code much more cleaner we’re going to create a model Getters and Setters include f.h so module to avoid writing lock unlock everywhere okay so in the
Main code I will have Set uh value to that I don’t know about locking a locking this will happen underneath it will happen thanks to these functions that now we will create so we start uh the thing now that you can clearly see is that there is a reason why I’ve
Chosen only long and Bulls because I want to use only two types of Getters and Setters for Boolean of for Longs and I’m settled for uh whatever they type in my uh simulation right so we start by booleans the first is going to be set bu
That is going to take a mutex right that’s the gist of it a poter to m6 and it’s going to take a pointer to a Boolean I call D and an actual value okay then the pattern is pretty straightforward you are going to lock unlock and set the value so you’re going
To mute Tex lock copy past unlock and in the middle you just have at that’s we’re going to reference the pointer is equal to Value boom that’s it you see now we’re going to do the function get bull so get Boolean same pattern type mutex
Mutex and I point it to the actual uh Boolean that I want that I call Value like that so we creat a return value Bull Red we copy here lock unlock and here we actually have the reading thing the reading of the value thread safe so
We say R is equal to at Value and then we simply return Red so you see the pattern is pretty simple we do the same for Longs so as you can see the pattern is specular we just simply uh change the data type and that’s it we have some
Thread save uh functions to get or set some values at the bottom I want another one which arguably is redundant but in my opinion it’s useful which is bull simulation finished and let’s say we pass the table that contains all the variables and we simply return here get
Bu table our m T So table newex a pointer to the Boolean which is table and simulation so a pointer to that Here Comes This simulation finished is just a wrapper for a get bu that we just created but I think that calling this function is useful all the time you see
Very clearly simulation finished simulation finished is simulation because we’re going to use uh the simulation finished a lot of times throughout all the throughout the code so for me the code being readable is part of being correct if the code is not readable yet it functions to me it’s not
Totally correct I mean because it’s not maintainable it’s difficult for myself uh to understand what I did so readability is very very crucial to me otherwise I will spend hours in the bugging without understanding what I’m doing all right so the thing is that we have to put all this function in our
Eder file so we go back in our Eder and we simply copy all the uh prototypes so we can use throughout our code I think these functions are super handy right without writing all the time lock and lock let’s go back to our dinner and now
We can start using after our while loop we do set bu we pass the table mutex by reference the destination is going to be um table all threads ready right Ste by reference and the value is going to be true like that so after our while loop now we set
This now we go back to our dinner function dinner simulation weit till Treads um let’s create this we’re going to create another model that I call Synchro utils some function to synchronize we’re going to need others also for the monitor thread so this file is going to prove useful include f. H so
What is the idea here in uh um in our dinner we have weight all threads this can be a spin lock namely we are making um the the actual thread run spin locking a while loop a busy waiting call as you want until all the threads namely
The flag is set to true this flag here so we’re going to do that we go back in Synchro and we say void weight all threats and as an input we have the table so type table pointer to that and we do as pin lock so while uh we use our
Save function so get bu table mutex 1% the value is table all threads ready right reference and here importantly not so while all the threads are not ready you just wait so you spin lock that’s it so spin lock to synchronize Fields start okay we just copy the Prototype and we
Pass in our header this is tedious but in C we have to do that inro utils boom done wait all threads we go back and now we have our synchronization thing every philosopher is going to actually wait for all the threads to be ready before going on all right cool we can remove
That to do so now let’s go back to our dinner and we can say at this point well now we are into business the simulation has started start of simulation or better start of simulation we put just before here so here we have to basically take the time of our start of simulation
So we need a chronometer we need a function that is able to give us back the actual uh time so we’re going to create this function we go back to our uols in which we already have our error exit function and we’re going to create our uh chronometer function thanks to
Get time of day we’re going to exploit get time of day so if you watch the manual we get that thanks to get time of day we get the time since midnight January 1st 1970 we have to use a which is time Val and inside this struct
We have uh the seconds since January 1 1970 and the usack which which are the microsc so we can exploit this get time of day to get uh whatever time we want seconds milliseconds micros seconds now we’re going to do that so we are going
To go get back time which is a long I call the function get time and as an input I want to use a specific uh time code in the sa Vibe of the the previous op code for mxes and threads so we’re going to create uh an enom uh the time
Code is going to be seconds milliseconds and micros seconds probably seconds are not necessary but who cares it’s very simple so let’s go back in our uh f. H and let’s create these enum codes for get time so enum enim time code we’re going to have second millisecond and
Micro second okay of course we’re going to type def everything type Ty code Type def all right so these are going to be all symbolic constants to our uh get time function let’s go back to uh utils so our get time is going to take as an
Input uh type time code which is time code all right immediately we’re going to create um struct time ball that I call TV and we call the function get time of day get time of day as an input we we get a pointer to our 10 value so
Pointer TV and the second parameter we don’t really need so it’s going to be a null so basically get time of day is going to set the seconds and the microc seconds inside my time value now the return value of get Time Zero return value indicates that could succeed minus
One and set er no if something so we’re going to make a silly control here so I say if I have some return value You’re Going to exit error even though it’s highly improbable get time of day failed like that all right now I have my uh seconds and micros seconds inside my
Time ball what can I do with that well I simply check the time code if second is equal to time code what do you do you want to return the actual seconds so you’re going to return time value I access seconds normally plus time value micros seconds and here we have to
Convert in seconds so we’re going to use scientific notation which is divided 186 right to make the conversion then the pattern is the same right else if milliseconds is equal to time code you’re we’re going to return time value do second this time we have to convert
This in millisecond uh which is going to be multiply by 1 E3 plus uh time value microsc this time divided 1 A3 all right the last one else if microsc is equal to time code you just return time value seconds per uh 1 E6 plus time value
Microc like that should be correct right else or exit we do wrong input to uh get time like that then here we get uh a mistake let’s do return 1337 this is just to trick I will never reach this line right because I I have my error exit but this
Is giving me an error so I just do this to trick that so we have our chronometer thanks to get time of the day we can get seconds milliseconds micros seconds elapsed from um 1970 that’s what we’re going to use to uh get the time in our
Simulation so we go back in our dinner and in our start of the simulation we’re going to call get time that first of all I have to copy in the other file otherwise not use it so and pass here so we do table start simulation is equal to
Get time in millisecond okay so after all the threads have been created we do a chronometer check we say all right the simulation now is started and we set the bll to all threads ready so our um dinner simulation here can so in our dinner simulation here at the top all
The threads can move move on can move on this line okay that’s basically the the idea by now then after that uh we are going to join wait for everyone so wait for everyone so I’m going to Res set I 2 minus one and I’m going to call while
I++ I is minor than table F number save Trad endle I want to call the join so uh I do table fos in position I I access the thread ID and I pass it by reference then give that I want just to join the tread here I don’t need anything I just
Pass null null null and I join uh so the cycle will be endless but in the case um all the philosophers are full this is going to be important okay so we need that point in if we pass over this line if we manage to reach this point if we
Manage to reach this line all fos are full okay all right let’s go back in our theer simulation and let’s move on now when we pass this line the philosopher will start uh its actual simulation right so we need to set last M time set the last
M time and then we start so it’s going to be while uh the loop is not endless because it’s going to be till the end simulation we will see that we have monitor thread that is going to uh check this so here we can say while not uh
Simulation finished we pass the table so F table do you remember right in my getter and Setter we have this simulation finished which basically returns in a thread safe manner the table and simulation um B so until the condition is not finished until the dinner is not finished what do we do
Well first of all the philosopher has to check am I full because in that case I exit so basic basically we have something like if uh f is full you just break the cycle you finished we leave it like to do thread safe so we are going
To see if this variable is accessed only by the the philosopher itself or only or also by the monitor so maybe we have to change this access uh in a short safe manner so we just change with f full get bull we are going to use get Bull and not directly F
Full but here is just to get the point then the simulation what is it so we’re going to call a function that I call it with the F three is going to be sleep so we can simply uh call our function you sleep precise you sleep and write that
Is sleeping and fourth we have thinking for think so we will call a function thinking with pass fill to do all right we need a function to write the actual status of the philosopher so write status namely function that U is going to write the philosopher is thinking
It’s sleeping is eating and so forth and a precise use lip because the real one is not precise and we need to be more precise so let’s start by creating a precise use liip function we go back in our utils and let’s do that so precise
Use lip the real one s indeed the use lip is going to give us uh at least the time we ask but very often is going to give us more because operating system um lagging uh laging things uh peculiarities let’s say there are many details but TDR us Li is not
Precise so we’re going to do void precise use slip as an input we take how much time right you slep use SEC you SEC we also need access to the data which are in the table because I want uh every time to check is the simulation finished
Simulation finished because if it is the case I don’t want to sleep anymore we have to go we have to clean and we’re over okay so the idea here is to you sleep the majority of the time not CPU intensive then true refine uh last um microsc with spin lock which is CPU
Intensive cont basically the CPU is not released so I’m going to need a variable that I call start and I say start is equal to get time in um microsc this time okay then I’m going to start a loop I say while uh get time in micros minus
Start is less than use SEC microsc right so we get a start variable which is the beginning of my Loop and then every time in my loop I get again the time I subtract the start and I get and I check if we already um sleeped for the amount
Of time requested here first of all I check if simulation is finished that’s why we need the table you just break right you don’t sleep anymore then to make this hybrid I’m going to use a variable I call Long elapsed and I say elapsed is equal to get time again a
Micros minus start then another variable long which is remaining let’s say remaining is equal to USC minus elapse all of this to to get a uh spin lock threshold what do I mean here say if the remaining time is Major than let’s say an arbitrary value which is 1
Millisecond uh you just call the function use Li even though it’s not precise to us SEC let’s say divide by two to get a buffer right you’re going to sleep you SEC divid by two if we have more than 1 millisecond as a reminder time you see it’s it’s kind of tricky
What I’m doing but hopefully is understandable else it means that the reminder time is less than 1 millisecond so if you have little time you are going to use a spin lock spin lock basically you’re keeping for yourself the CPU and you do while the same condition as here
At the Top Copy past spin lock like that maybe this function as I as I did is kind of confusing but um basic basically it’s just an hybrid I’m use sleaping for the vast majority of time when I reach a certain threshold which is 1 millisecond
In our case this is just a threshold when this remaining same is less than this I’m going to spin lock otherwise you’re going to call use lip Okay so this will give us precise or more precise slips than the actual uh system function you slep which is very often
Not precise all right so we have our precise use slip function that we can use so I’m going to copy this and pass in my field. H into utils here it comes let’s go back to dinner so precise you sleep is done now we need a function
That will write um the status let’s do that let’s create another model write this time the pattern is always the same we include field H so we have to write uh the output in this fashion like time in milliseconds F ID action namely a of fork is leaping is thinking okay we have
To pay attention that this has to be done thread safe so we need a lock we go to uh field. H and in our table we create another lock the table mutex is to read this data right on the contrary table mutex right right lock just for right of course it’s called for
Consistency mtic right mtic all right back to init so we are going to also in it this right music and now we can use it back to right right M all right let’s do it the function is going to be boid bright status um then we’re going to take again
The status of the philosopher you know perfectly well the pattern we’re going to create an enum with all the states available F States so it’s going to be something like that right another enum with all the states eating sleeping thinking here I use stick first Fork and
Take second Fork because this is going to be useful for the buing purposes and died so we have all the states type fill status okay let’s go back to right so my right status is going to take type fow status I call status then it’s going to
Take of course the F so the is simple we’re going to uh save mutex lock um so filo table uh write mutex code is going to be lock and at the very bottom unlock and in the middle we simply say if take first Fork is equal to status or take
Second Fork is equal to status and uh simulation is not finished you see this is important F table bang here not finished what do you do you call the printf and you put your your your actual string you say uh percent LD long digit which is going to be the time you’re
Going to create um a space of I don’t know six we’re going to do it left left Justified with is minus this is just how the have works is as it has all these format specifiers uh I’m going to do it white the color and then reset so this
Is the time stamp milliseconds um then all right percent D has taken of work new line so I have these time stamps for methods and the actual string now at the very top of my function I want to do long elaps it which is the actual time
And elaps it is going to be uh get time in milliseconds okay so for every print F I’m going to use that which is elapse and the second is going to be F ID okay so this is the the thing right we have check the the actual status then given
The status you’re going to print the milliseconds elapsed the string and so forth so so this is repet just a repetitive thing right there’s no nothing to really understand the thing is that I want some right status which is also in at the back mode so at the
Very top I’m going to use a Boolean which is a Boolean the bug and here I say if uh the bug is Boolean you call another another function that I call write status the bug and I pass stat status the pointer to philosopher and elaps the time else we are going to use
This okay important thing is that this has to be done at the very top so I’ve WRA around this Logic the Locking and unlocking of the mutex and uh then uh I will Implement now this is pretty repetitive there’s no need to explain I will show you the final result all right
So this is the final results as you can see I have here at the top uh the Locking and the unlocking right so all this code is like meshed inside the Locking and unlocking and it’s pretty simple in the case I want to the back a
I’m going to call this function and I will show you otherwise you’re going to write normally here you see a lot of stuff because I have ask escapes which make the thing quite cluttered and the thing is that I have while not simulation finished call in
Every um if arguably it is a better design to put if simulation finished at the very top and then just Escape but I don’t know in a multi traded environment this can happen at every time so maybe it’s better like that I don’t know frankly and uh the thing is that this
Function is not cool all the times right it’s going to be a CPU intens because we have the short circuiting thing right this going to be C only if the first one is true you see so probably it is better to put at top probably this is a better
Design but nonetheless it’s not crucial the thing is that all this stuff is wrapped around around the Locking and unlocking and here at the very top I I put if philosopher is full you just return uh this because when uh the philosopher is full I just want to
Finish I want to write anything uh I want the simulation to to stop okay now we’re going to check if we have to do tread safe uh tread safe we I get bu we will see later when we’re going to create the monitor now let’s see the
Debugging uh uh way as you can see it’s a static function and it’s basically the same the only thing is that I have emojis I have take the first Fork take the second Fork so now you understand why I have this specific enum to to know what to do
And then I have for the eating how many meals have been eaten by the actual philosopher so I know I have a counter of all the meals taken and when a fork is taken I have the number ID of the actual Fork uh taken right this is pretty handy for the bugging purposes
And so the thing is that I have emojis and I know the fork that has been taken and I know the number of meals that has been done all right I’m going to use um a Define in my fi h uh like that Define the bug mode by
Default is going to be zero so this is going to be for the right function right function macro okay that’s the idea all right let’s go back to our dinner but before let’s copy this right status in my Adder here it comes and now we go
Back to dinner so now we have both right status and precise you sleep so for the sleeping what do we do write status stat is going to be sleeping f and here we use our macro the bag mode and then we call precise use lip which is going to
Be equal to F table uh time to sleep these are going to be constant values so risk conditions are not going to be an issue and F table like that so now uh let’s implement the actual it function which is the most important thing for a philosopher so let’s go up it routine
The idea is simple we have grab the forks so here having first and second Fork is Andy right second Fork is Andy I don’t worry about uh left or right anymore then we have the actual eating which is right that you are eating update last meal update meals counter
And eventually bull fo okay three release the forks let’s do that so it’s going to be a static void eat as an input we have a pointer to F right so let’s do the first point so save mutex handle we have to lock the first Fork so
It’s going to be F first fork and Fork right by reference because my struct is also the ID so here I need also to say explicitly I want the fork I don’t want the fork ID and the code is going to be lock we do the same for the second Fork
Of course in between we have to write the actual status which which is Tick for first fork and take second Fork all right that’s it for the first step Second Step actual eating now I have to set the last me time and I’m going to do
It immediately uh this is going to be a value that will be read also by the monitor tread every time he’s going to check if the elapsed uh time between meals is Major than time to die so I have to do this in a tread safe manner so I have set
Long and here I want that every philosopher as a an internal mutex that will be used with the monitor okay so I need to give a a mutex to every philosopher we go back to f.h and we give to the philosopher a mutex so type mutex filo mutex uh useful for races
With the monitor that we will create you will see all right we go back to init and for filo in it for every filo we have to in it also the mutex so safe mutex handle f f mutex operation code is going to be of course in it okay like
That so now every philosopher is going to have his internal newx that is going to lock and unlock to update last Mill uh time let’s go back to diner and I’m going to set long F of mutex destination is going to be F last me time and the
Value is going to be get time in millisecond right like that then we have to increase the Mills counter but this value is not going to be checked by the monitor you’re going to be checked by the philosopher itself so I can simply increase normally so filo Ms counter
Plus+ and then I simply write the status e think the Pug mode perfect and of course I have the precise use liap which is uh F table time to eat and a pointer to the table now I do an internal check if the uh philosopher is full what do I
Do I say if fil um table number limit Ms is Major than zero right because this is both a Boolean but also a value and filo Ms counter is equal to fil table number limit Ms well in this case it means that the philosopher is full so we’re going
To set bull we’re going to pass the philosopher mutex so F mutex uh the destination is going to be fful to True right all right that’s it so you see see that the eating phase is like that at the very end we just have to unlock the
Forks unlock unlock now you can clearly see what do I mean by take the forks basically is locking first second Fork writing the status then eating which is basically updating the last meal time updating updating the Mills counter writing the status so you see why the update of the Mills is before the
Writing of the status because of course I want to write the right the the right number of Mills and then you just sleep for the amount of time requested then you simply check if we reach the full condition namely the number of meals Ean is equal to the limits if this is the
Case we set in a thread safe man manner the the actual Boolean true and then we just simply simply release uh the forks so this is the it routine all right so it is done now we still have to make the thinking routine let’s do static uh void thinking take a pointer
To the philosopher and by now we just simply write the status thinking and that’s it then we will change some values because thinking is the only value that we can really model because time to die time to slip onto it are fixed time to think is
The the only one we can module to make the system more fair all right we think we already have a minimum viable uh philosophers project and now let’s try to launch with this input as you can see this is what is going on we have all the
The threads that are writing stuff in the standard output this is the normal not the bugging output here if I change in f.h this the buag mode to um one and compile again Everything Will Change you can see now that um we have the MS consumed by the the actual philosopher
We have some emojis and we see the forks right we see the actual philosopher that has taken philosopher for example here we can see the output and I can see one has taken the first Fork which is zero and one is taking the second Fork which
Is one but it’s not what I want let’s go to init and indeed there is a mistake here F ID model true I forgot to put equal equal zero of course because I want the uh the even philosophers to take the first for let’s try again okay
Let’s see let’s say one is taking the first Fork which is the fork number one and the second should be zero one is taken the second Fork which is zero perfect uh let’s see philosopher number two there he is here it comes I taking the first fork and the second which is
One and two all right perfect you see how immediately useful it is this way of uh the bugging right this output of the bugging here you have the time stamps and white on the left and now we have to keep going on with our uh dinner because
We need to check when a philosopher actually is going to die to do that we are going to need a monitor right we’re going to need a monitor thread that is constantly searching for these de uh philosophers so before the start of the simulation we’re going to create our
Monitor thread here it comes monitor it’s going to be safe thread endle and of course here I need the app pointer to the actual thread we’re going to put inside uh f.h our table right we’re going to do p thread type monitor like that is going to be the actual monitor thread
Searching for death now let’s go back to dinner here and I give us an input exactly that thread uh is going to be table monitor by reference the function is going to be monitor dinner data this time is going to be the actual table and
The op code is going to be create all right this is is our monitor uh to do now let’s um create another file I call monitor. C or monitoring so we include fill. H and we are going to do void star um monitor dinner void star uh data we
Retrieve our table so pointer to table table is equal to pointer to table data like that the very bottom we say return all and here I’m going to need another synchronization thing which is that I have to be absolutely sure that all the philosophers are running before uh
Starting their controls so I’m going to do uh make sure all fos running so I can say while not all threads running a function that we will Implement and we will see the inputs to put you just uh busy weight all threats running this is another uh Synchro utils
We’re going to do that so we have monitor busy weights until all threads are not running it’s going to be bull all threads running and what can be the idea here well we can have that at our dinner um essentially at this level after weight all threads we have Synchro
WID monitor we can increase uh a table variable counter with all the threads running so let’s do that we go to fi. H and we use a that I call thread running number okay then usual D thing we go back to init and we set this value is
Zero okay now in the dinner um what we’re going to do we’re gonna actually increase this value basically when every philosopher is gonna pass this spin lock right it’s goingon to start the simulation and while he is starting is going to increase the value of the
Number of threads that are running so we say set long but that long is not correct we need an order which is increase long increase long you’re going to lock the table mutex so it’s going to be filo table table mutex um and I point her to the actual value which is filo
Table threads running number something like that all right so of course we have to implement so very simple we go in our Synchro utils and we’re going to do that so void increase long and it take us an input mutex of course mutex and a pointer to a value the pattern is always
The same locking the mutex lock unlock and just increase say at Value Plus+ like that very silly function to increase along in a thread safe manner that I use specifically to increase the number of threads which are running to Synchro uh with the monitor okay the monitor is going to use these old
Threads running to indeed fetch this value and make a comparison if the number of threads running is equal to the actual total number of threads so we’re going to implement all threads running this function let’s say is going to take a pointer to autex of course a pointer
Uh to the threads which are running and the value of f number we can say F NBR even though it is inside uh the table struct to make the code more readable so we have to read the value so bull return we set initially return to fults fals and return
R and in between we have to actually read right we have to read so I’m going to lock and unlock and here I say if at threads the number of threads running is equal to F number Red is equal to true that’s it that’s my old threads running
Function is and what the monitor is going to use so now we just copy these prototypes and we put in our other file increase long as well and now we go back in our dinner so you got the point right in our simulation every time we pass uh
This uh first spin lck every philosopher is going to increase the number of the threads which are running if we go to the monitor we have while not all threads running that we just implement the mutex is going to be the table mtic the pointer on threads uh is going to be
Table threads running number by reference and F number is going to be table fi number like that okay so we manage to implement this function again so my monitor Waits until 100% all the threads are running before making all is control all right spin locking so this is going
To be spin lock till uh all threats run then the actual thing which is while essentially uh like in our dinner see here go back every philosopher as while simulation is not finished the same thing will happen with the monitor I say while simulation is not finished what do
You do you do your algorithm basically constantly checking if the elapsed time of the philosopher not eating is Major than time to die now we will implement this so what is the idea behind this monitor well this is simply like a referee it’s a referee that is constantly checking all the philosophers
Right is going to check the time stab right elapsed between last M time if this elaps time is big is bigger than time to die well the philosopher is that and if this is the case well it’s the end of the simulation so in that moment
The flag end simulation is going to be turned on and everything is finished we have this refering we have to implement uh this ID code here at the very top I need an iterator again in TI and here I do I is equal to minus one and think
While Plus+ I is minor than table F number what do you do you’re going to say ay if then a function that now we will create f diet best table philosophers plus I right this point to arithmetic what do you do you’re going to set the bull and simulation taking
The table mutex so table and simulation a reference to that the value is going to be true okay and then you write the status died we pass the table fos plus I the bug mode that’s it that’s basically now we have to do the is died function and of course here
I want to stop the inner well Loop and simulation is not finished again every time I check for that now we Implement um the the is died fil function so let’s do static bull Phil Di and it takes a pointer to the actual philosopher so
What’s the gist of it here we have to check last Mill time last Mill if this time is Major than time to die we set the return value to True okay so I’m doing long elapse then I will do the same long time to die just to not the
Reference too many times making the clote clearer so elaps is going to be uh get time milliseconds minus get long uh we’re going to uh lock the the philosopher MX so fil mutex fil mutex because here we have a concurrency between the Monitor and the pH for long
Value is going to be filo last me time okay by reference time to die is equal to filo table time to die like that I just use this internal variable to not use this long referencing and then why do I do I simply say if elaps is Major
Then time to die you return true so the philosopher has died else you return false okay like that one important consideration here that we have to make is maybe the philosopher is full so it’s not died it’s simply he has simply finished its own simulation so maybe
Filo is full so at the very top I say if uh get bu uh filo mutex filo fo you just return false because the philosopher has finished this simulation it’s clearly death but not because is the system is not working but just because it has stopped its own stuff okay let’s go back
To the and let’s see what we still need to do so we have wait for all threads increase long so we can synchronize with the monitor uh just before that here we need set time last meal so it’s going to be uh F or better set long filo F mutex
That’s is going to be uh filo last me time and the value is going to be get time M second like that okay so we’re going to set the last me time this is an important value then we increase the number of philosophers and then we get
Into our simulation it uh we have it sleep and think all right let’s go back to dinner start here at the very bottom we still have to handle one philosopher so we’re going to do a function that I call L filo or better I’m going to create another tread just to make it
More real so safe um tread and all I take table uh philosophers in position zero this time uh tread ID function is going to be Lan fil data is going to be the philosopher table F on position Zero by reference and then I simply create
This big boy all right so we have a thread for a longone filo we create the function Lan filo it’s going to be the same algo and as the normal philosophers just um we’re going to do some changes we’re going to fake to lock the fork lock the fork sleep until the monitor
Will bust it will bust okay so as usual void star uh lone filo void star Arc we retrive the philosopher a pointer like that and same weight all threads so F table like before even though it’s only one set long filo mutex filo last me time get
Time a millisecond like that we increase the number of threats that are running so our monitor is ready is it’s able to to go then I write status take first Fork even though I’m not taking this is just for uh output uh purpose so we are
Faking to check the actual fork and then I simply say while simulation finished table while not simulation finished you you sleep for uh 200 millisecond okay I can use you sleep I don’t really care at the very bottom we put return all so basically the long philosopher is like
An noral philosopher the only thing is that he keeps sleeping for 200 millisecond until the monitor will bust him we bust him will find him because the last me time is never going to be updated eventually let’s try to compile and see what do I mean by that so let’s
Launch with one philosopher is not working it’s an infinite Loop allegedly so there must be an issue a few moments later the problem is here I guess time to Die the thing is that I converted time to die at the very beginning right when we have inited uh remember when we
Were parsing at the very bottom here time to die was already converted to microsc but here I got it wrong because here we are doing millisecs so time to die divided on E3 like that and as you can see it works right now I have a little mistake but doesn’t matter so we
Have the first philosopher that is taking off work and after some time for example once second has been busted by the actual uh monitor tread that’s the thing I wanted so pay attention here that time to I convert back to uh Millie so let’s try to launch with five Mills
We get something like that and we get this bug but we don’t really care the thing is that as you can see we have philosophers that are doing five meals 3 one 4 two get right then let’s try to check if the monitor works as you can
See it finds a Deb philosopher given the time stamps let’s try 300 okay it seems like it’s working and now let’s refine our code going back to my dinner start if we manage to reach this line as we said it means that all the philosophers
Are actually full so here we can say set B uh table newex table table mutex table and simulation to True right we can set the end simul ation to true and this time the end of the simulation is not going to be uh set by the monitor right
This is going to be set by the main thread because this is the main tread is not the a philosopher tread it’s the main thread the one that is launching all the philosopher if we manage to read this line is that is because we have crossed this join namely all the
Philosophers have finished their own simulation so we set this two true why is that well because also the monitoring is waiting for the simulation finished right so it is a double uh way right you get my point the simulation finish flag can be turned on by the actual uh
Monitor or by the main uh thread is going to turn on this this thing hope this is clear what I’m saying so let’s go back to dinner so after that we are going to join also um safe trade Ando we’re going to join also our monitor so
Table monitor because the join is not only Waiting For Thread but is also cleaning resources this is useful for uh not having licks okay so I’m going to join also this then we go back in our main and we have to create our clean function that is going to clean everything right with
No leaks we put this in our utils clean and we take as an input app poter to the actual table uh let’s do that we also have to clean all the stuff inside the philosopher so I’m going to do type f point to F and an iterator i is equal as
Always to minus one and I say while Plus+ I is minor than table filo number filo is equal to table filos plus I and here I have to destroy the mutex of the philosopher so save mutex sandal um filo fil mutex pration code this time is
Going to be destroy like that then I do the same for the table mutexes so save mutex handle uh it’s going to be table write mutex and table mutex and then I’m going to free the forks and the philosophers table Forks free table philosophers that’s it that’s the clean
Function destroy the mutexes and um free the actual Malo elements I’m going to copy this and put my adder and now we have our beautiful claim function so we can cancel this now let’s make some tests okay this works now with this we have that nobody should die right on the
Contrary I have that some philosophers are dying what is the problem here all right this doesn’t work uh in this condition philosopher shouldn’t die when they are four there is a bug lering somewhere let me find out a few moments later all right it seems like I found a
Bug which is this one I call use liip not on RAM remaining but on use liip again this of course bug bug SP now you probably see that is happened immediately right I will cut all the silences and all the best for Italian friends but this took a lot of time like
All the times this silly mistakes so let’s try now and as you can see it works the system keeps up even though I have uh many applications open it seems like to be alive the thing I want to show you is that when we have uh an OD
Number of philosophers like for example five here the system should keep running indefinitely but sometimes can not run and now I will show you the reason first of all let’s go to field. H and let’s change the BM to zero I’m going to compile again and launch so we’re going
To get a normal output and as you can see I’m going to copy this and I’m going to put in this marvelous website which is philosophers visualizer that is going to show you exactly what is going on now you see the problem on end we have one
Philosopher that is thinking too long is thinking for too long and uh we have a philosopher that is not thinking at all we have some philosophers that are just eating straight off the thinking phase so I want more control over thinking I want more control I want the system to
Be more fair so as you can see for all philosophers we have this system which is not fair not fair it means that um not every philosopher is going to respect its own turn now I’m going to discuss with you some my observations that I’ve made on the philosopher the
Dining philosopher problem this can be wrong frankly I’m not totally sure but these are just some empirical observations we discuss this together so when we have an even number of uh philosophers I’ve noticed that uh when time to eat is less or equal than uh time to sleep there is no thinking time
Namely the symmetries of the system imply that there is no thinking time thinking time is the contention time is the time spent um waiting for the forks right but in a system when we have uh even philosophers and time to eat is less equal than time
To sleep there is no contention at all as you can see right the symmetry of the system implies that there are no time to think at all just watch the first case uh every time when a philosopher finishes to to sleep can immediately start to eat because the neighbor is
Sleeping namely the neighbors right both neighbors are sleeping still all true for uh when the time to sleep is equal to time to eat we have a perfect symmetry of of the system you see immediately it sleep it sleep it sleep there’s no need for thinking time the
Thing is different when the time to uh eat is Major than time to sleep as you can see in this case right we have 200 100 and in this case time to think is equal to 100 forcefully by the system by default right the system implies that there it’s necessary to have 100
Thinking time so we can say that the thinking time exist in a system when we have an even number of philosophers when time to eat is Major than time to sleep this is not true on the contrary when it’s minor equal than time to sleep so
Now I will try to show you why when the system is even when we have an even number of philosophers I don’t want to control the thinking time this is going to be uh done by the actual symmetries of the system itself let’s pretend we
Have a big slep time which is still um minor than time to eat right what is going to happen when a philosopher is going to finish to uh to sleep it’s going to wake up and he going to try to reach for Forks but it cannot immediately reach a fork because it’s
Blocked by The Neighbors which are still eating namely the forks are locked right the philosopher simply cannot eat by the symmetries of the system after he has finished to sleep okay forcefully there is some thinking time in a theoretical scenario right if the system works smoothly perfectly same Al true if the
Sleeping time is very little right when the philosopher is going to wake up is going to still find the neighbors eating so the forks are going to be locked so tldr for even philosophers the system is already Fair because no filo can eat two times in a row you see because it’s
Blocked by the neighbor by default by the system uh design by the system architecture if you you want right now let’s watch this for odds philosophers we get this for odd philosophers for example 3 800 200 100 when time to eat is equal to time to sleep we have time
To think which is equal to time to eat or time to sleep just watch the images you can see very clear what is going on right when I have time to sleep which is Major what is happening we have that time to think is equal to time to eat
Per true minus time to sleep time to eat per true this time because because we have to wait for our neighbor to finish eating when we have odd philosophers we don’t have a perfect symmetry so look here when we have 200 time to eat 300
Time to sleep we have 100 time to think and when we have 200 400 we get zero right it’s time to think and when we have 200 350 we have 50 because 200 per 2 400 minus 350 50 millisecond to think again this is stuff mechanical right it
Is implied by the system itself so this is when time to eat is Major than time to sleep we have the same thing when we have 200 and 100 we get 300 milliseconds time to think and as well when we have 250 we get 350 millisecond so what is
The take home message well if philosophers are odd uh we get that time to think is equal to time to eat per true minus time to sleep right in every case even in the first case when the values are equal so in this case in the
First we have time to think is equal time to eat per two minus time to sleep you just have a visual understanding here thanks to the marvelous uh philosopher visualizer now why all this story well we want to control when philosophers are odd the thinking time because we can have that one philosopher
Can actually eats immediately after he has slept in this case if he don’t control just watch this combination we have the second philosopher that eats sleep and then goes to think the third it sleeps but doesn’t go to thing immediately starts to eat making the system not fair and making the system
Not working the second philosopher is going to die even though in the system shouldn’t die so let’s have a visual understanding of what I’m saying is pretty weird right I think it’s pretty complicated so let’s say let’s say we have philosopher 3800 200 and 200 and let’s start the simulation so initially
We get uh philosopher number two that is locking Fork number one so philosopher number one is blocked right because the fork is locked and then we have philosopher number three that is locking the uh lock number zero the fork number zero but philosopher number two as locked the fork number two so even
Philosopher number three is locked right you see the image I think it’s clear so now philosopher number two can eat and that’s what he’s going to do it’s going to eat right then he’s going to release the force then what what happens we have that philosopher number one is going to
Lock his Fork but the other Fork is already locked by philosopher number three that is going to lock the other fork and he going to eat in this time philosopher number two is sleeping right philosopher number three is eating like that then philosopher number three is going to release the forks and finally
We get that philosopher number one is going to lock the fork okay philosopher number two pay attention here has finished to sleep but is forced to think by the system you see it’s forced to think because philosopher number one has locked the fork so philosopher number one is eating philosopher number three
Was leaping now what is going to happen philosopher Number One released the forks and now what is going to happen what do you think what if ear number three is faster than number two to take the forks right because of the system possible conditions we are in random
Area it’s the operating system scheder that is going to orchestrate everything so let’s pretend number three is faster what he’s going to do he’s going to lock both Forks as you can see and it’s going to eat it’s going to eat again forcing number two the think another time right
Because there’s no control right there is no control on the thinking and I want to act exactly here I want to avoid this kind of scenario double thinking the system is not fair this can work but in practice won’t I mean the system can
Work it can run but at time you will get this scenario so we are going to forcefully control the thinking time a more robus in solution when PA a thinking time if available so we’re going to think is there some thinking time available you saw the formulas if
There it is available we’re going to think for a custom uh thinking period that you will see in code so after spping every time a philosopher is for the think a little bit this is my solution to the ding philosopher problem I don’t know if this is correct I don’t
Know uh but thinking is the only variable in which we have control of so here just before entering the loop I want to desynchronize the filos basically I want to um make the uneven or odd philosopher wait for a custom amount of time just to have a perfect synchronization while starting this will
Help In fairness so for even philosophers I will have a micro waiting milliseconds waiting just to desynchronize avoid too much for contention if the system contains uh odd philosophers we’re going to start by thinking now you will see what I mean code I think would be easier the
Function is the synchronized philos and takes f as an input we’re going to implement this and we’re going to put this in Synchro utils so this is a function make the system Fair trying to make the system Fair all right so it’s going to be void the synchronize filos a
Pointer to the actual philosopher and I say if the system contains an even number of philosophers so if F table F number model 2 equal Z else it’s an odd system what you want to do you just want to make a philosopher sleep for uh F ID
Model true is equal to zero we’re going to make the dude you sleap for uh let’s say 30 milliseconds uh 30 milliseconds because is half the time of the minimum time available that we can go that we can give to the system right which is 60
Milliseconds so it’s going to be 3 E4 table else if the system is odd I’m going to say if filo ID uh model true we are going to start by thinking so this is a function that now we have to create very well I don’t remember if this is
Static or not so we go back to dinner we remove the static the word and we put this into uh f. H say fairness so Synchro utils thinking TT as an input philosopher okay so let’s elaborate my thinking function given given what we have talked about immediately I say if
Um filo table fil number model 2 is equal to zero you just simply return first of all of course you just write the status so just so if the system is even we don’t care we don’t care quick refresh right if we have a time to eat
Minor equal we don’t have thinking time if we have time to eat major than time to sleep we have a thinking time but as we so the system itself would take care of the fairness of the system right because the neighbors are going to be eating so I don’t care the system is
Already um fair I don’t care system already Fair now odd there can be scenarios in which not fair not always Fair what do we do in this case first of all I want some local variabl here which are time to die time to eat time to
Sleep I don’t want every time to fetch with the proper notation to sleep time to think okay time to itat is equal to F table time to itat time to sleep is equal to F table time to sleep time to think time to think is equal we just saw
Previously right in an odd system what is that the thing just watch the images here the formula is clear is time to eat per true minus time to sleep of course in an ideal scenario I’m talking about an ideal scenario so given that we’re going to just plug this formula inside
Time to think so it’s going to be time to eat per two minus time to sleep this is the possible time to think available time to think let’s say that available of course this value can be also negative right in this case we say if uh
Time to think is Miner than zero of course doesn’t make any sense to have time to think negative so you say time to think is equal to zero on the contrary uh you’re going to say here is where the precise control I want to make onfi it’s exactly here I’m going to say
Precise you sleep and I’m going to say you are going to sleep time to think which is the the time available not all the time but I’m going to say for example per 0.42 forcefully I’m going to say at least you philosopher you’re going to think
42% of your thinking time after you uh wake up this is an attempt to to avoid a philosopher eating two times in a row I hope you understand what I’m trying to do here right we are in this moment in which uh philosopher number three is faster than philosopher number two and
It’s going to e uh again forcing number two to think again making the system not fair being smart we are going to force the philosopher number three to think for uh some time giving time to Phil philosopher now true to take the fork and making the system more fair that’s
What I’m trying to do and then we leave the uh 58% of the time to the actual system itself to take care of itself uh now one thing that I want to do is to change this thinking I want to put here also a Boolean now I will explain you
Why here I’m going to put false on the contrary just before so let’s change the Prototype so here I change the thinking um just for output reasons going to put a FSE there I’m going to change the fill. H thinking is taking a b a COR pre
Simulation because the first time I call thinking is just before the simulation actually starts and I don’t want to um write in the Su output that philosopher is thinking it’s just for synchronization reasons so we go back to dinner so here is false here I have desynchronized fos but in synchr utils
You put here true okay then we go back in thinking here R dinner and you say if not pre simulation here we just add the Boolean bull pre simulation youve write the status okay as simple as that it’s just a a minor thing but that’s it let’s
Try now to launch this code so it’s going to be 5 800 200 and 200 and as you can see this time having a refined uh control over the thinking period just after the sleeping Nam I’ve used 42 empirically it seems like the 42 is working it’s just a magic number as you
May guess 42 no specific reason to do that I just want to say hey when you finish to to eat just wait a second just think let the system self synchronize and do its own stuff okay let’s try with four here should be 400 200 of course
This is going to die because we don’t have enough ping time let’s do 410 as you can see the system works even though I have many applications open so there are many threads running around ins inside my computer it seems to work properly uh if we have an fixed number
Of meals for example five it works let’s just change here the debug mode to one so we can have a better appreciation of the output let’s do again five as you can see every philosopher has taken five meals and then has finished his thing uh let’s do this case in this case
A philosopher should die and overall it seems like uh everything is fine okay all right this has been pretty long arguably complicated I don’t know if the solution is 100% correct this is just my implementation I will push all on GitHub so maybe you can uh check further this
Thing hopefully this was useful and yeah thank you very much for watching my friend enjoy
10 Comments
S A V I O U R !!!!!
🤓
once again you saved my day 😉
thanks for the videos and all the lectures
Hello, man. Thx for a great video again;) Where did you find in subject 60 ms? Why should it be major than 60 ms?
By the way, did you find how to convert program from threads to forks with semaphores?;)
Hi, bro. Cannot join discord. It says that the link is out of date.
Hi from 42 Barcelona, I've been following you for quite a long time already and atm we are more or less at the same pace. Really excited about the Ocean's 42 proposal and hopefully I will be able to post some info about the so_long project 🙂 Keep up with these type of videos as it helps a lot of people!
hi again! May I ask why you strictly "thinking" at some time interval? as far as i invesitage your code from philosopher visualizer it gives me some kind of a laggy situation. I mean it seems philosophers can able to eat instead of think. In my opinion you actually don't need to usleep or usleep just 1 millisecond or so. Good code btw!
Big up from 42 Lausanne ! Really Useful video, thanks !
as usual , Oceano big thanks to you bro ! I make this with you from scratch , and now im gonna to evaluate this !
Good luck !
You saved me from the black hole! Thank you and keep up the good work! Are you going to do the MiniShell tutorial? 👀