#1
Posted 02 March 2015 - 03:31 PM
I have to ask and this is a very vague question,
How do you implement multitasking into an OS? I have tried many times, but can't seem to get my head around how it would work,
Any help would be awesome thanks!
- Danny -
#3
Posted 02 March 2015 - 04:16 PM
#4
Posted 02 March 2015 - 05:06 PM
Lyqyd, on 02 March 2015 - 04:16 PM, said:
Okay, so I wanted to make a new OS as a small test, as I looked at building on my old one, but it would be a lot more work, so instead I am gonna start again.
So here are my questions:
1. How would I create a 'coroutine manager'?
2. How do I redraw the new coroutine every time? Also if I draw on one and then want to change to a different task how does a coroutine redraw everything? and store the old one? Window API?
3. I think I am also talking about buffers too?
4. This was a little too much to wrap my head around... I think I am asking for some specific details... As I don't understand how Lua can even do this also...
Thanks a lot for all your help guys
#5
Posted 02 March 2015 - 06:12 PM
2. You don't "redraw" the coroutine. The coroutine will draw itself, but your manager will probably assign a window to each routine, which will be redirected to while that routine is running.
3. Yes, buffers are helpful.
4. Simple Explanation of coroutines:
You have a program. The program runs another program until that program yields, and saves the result to use as a filter for events.
This is already using a coroutine, however it is not using it in any useful way. Now imagine we have two coroutines. Coroutine A and Coroutine B. You first run A until it yields, then run B until it yields, and repeat. If a coroutine's status becomes "dead" at any point, you'll want to remove it.
Really, just read the tutorial. It'll do a much better job explaining than me.
#6
Posted 02 March 2015 - 10:27 PM
KingofGamesYami, on 02 March 2015 - 06:12 PM, said:
2. You don't "redraw" the coroutine. The coroutine will draw itself, but your manager will probably assign a window to each routine, which will be redirected to while that routine is running.
3. Yes, buffers are helpful.
4. Simple Explanation of coroutines:
You have a program. The program runs another program until that program yields, and saves the result to use as a filter for events.
This is already using a coroutine, however it is not using it in any useful way. Now imagine we have two coroutines. Coroutine A and Coroutine B. You first run A until it yields, then run B until it yields, and repeat. If a coroutine's status becomes "dead" at any point, you'll want to remove it.
Really, just read the tutorial. It'll do a much better job explaining than me.
I kind of get it..
So the coroutine will redraw itself when I resume it?
Also could i use normal apis with it, like redirect to it and then draw? or do I have to do the window.write() etc...?
Will have a look thanks!
#7
Posted 02 March 2015 - 10:45 PM
Whether or not that coroutine draws anything entirely depends on the function you built it out of. Resuming a coroutine doesn't automatically redraw everything that function had drawn in the past. The functions for dealing with coroutines have absolutely no control over your display.
If you want to run multiple scripts at the same time via coroutines, and are worried that they might draw over each other's output, that's when you'd rig up a display buffering scheme - redirect each script to a separate buffer object, then manually trigger a redraw of that before resuming the associated coroutine. This is exactly how multishell operates, using the window API to handle its display buffering.
#8
Posted 02 March 2015 - 10:57 PM
Bomb Bloke, on 02 March 2015 - 10:45 PM, said:
Whether or not that coroutine draws anything entirely depends on the function you built it out of. Resuming a coroutine doesn't automatically redraw everything that function had drawn in the past. The functions for dealing with coroutines have absolutely no control over your display.
If you want to run multiple scripts at the same time via coroutines, and are worried that they might draw over each other's output, that's when you'd rig up a display buffering scheme - redirect each script to a separate buffer object, then manually trigger a redraw of that before resuming the associated coroutine. This is exactly how multishell operates, using the window API to handle its display buffering.
Ahh okay, so how exactly do I index a coroutine? As in if I want to make a tab based multitasking system, how am I able to index it into a table? like:
local task1 = coroutine.create(afunction()) local task2 = coroutine.create(anotherf()) table.insert(taskstable, task1) table.insert(taskstable, task2)
Then run it like:
coroutine.resume(taskstable[1])
EDIT:
Also how would I open a file and run the contents of that program in a coroutine?
Edited by DannySMc, 02 March 2015 - 10:58 PM.
#9
Posted 02 March 2015 - 11:03 PM
DannySMc, on 02 March 2015 - 10:57 PM, said:
local task1 = coroutine.create(afunction()) local task2 = coroutine.create(anotherf()) table.insert(taskstable, task1) table.insert(taskstable, task2)
This would more of less work, but when creating your coroutines you need to build them out of functions. "afunction()" runs a function and returns the result, and you can't build a coroutine out of that result (unless that also happens to be a function) - you'd generally just pass in "afunction" directly.
DannySMc, on 02 March 2015 - 10:57 PM, said:
Look into the "loadfile" function.
#10
Posted 02 March 2015 - 11:15 PM
Bomb Bloke, on 02 March 2015 - 11:03 PM, said:
DannySMc, on 02 March 2015 - 10:57 PM, said:
local task1 = coroutine.create(afunction()) local task2 = coroutine.create(anotherf()) table.insert(taskstable, task1) table.insert(taskstable, task2)
This would more of less work, but when creating your coroutines you need to build them out of functions. "afunction()" runs a function and returns the result, and you can't build a coroutine out of that result (unless that also happens to be a function) - you'd generally just pass in "afunction" directly.
DannySMc, on 02 March 2015 - 10:57 PM, said:
Look into the "loadfile" function.
I made this: but why does it not work?:S I added the parent in because when the coroutine is created it directly snaps to it and won't run the main() function?:S (In sublime it is nicely indented but these forums don't like it )
--Test: function maths() while true do print("> Maths stuff") print("Press 1 to continue") print("Press 2 to go back") local args = { os.pullEvent("char") } if args[2] == "1" then for i = 1, 10 do print(i) end elseif args[2] == "2" then coroutine.yield() end end end function calc() while true do print("> Calculator") print("Press 1 to continue") print("Press 2 to go back") local args = { os.pullEvent("char") } if args[2] == "1" then print("> 1st number:") local nNum1 = tonumber(read()) print("> 2nd number:") local nNum2 = tonumber(read()) print(nNum1.." + "..nNum2.." = "..nNum1+nNum2) elseif args[2] == "2" then coroutine.yield() end end end function main() while true do print("Press the numerical number for either option") print("1. Maths") print("2. Calculator") local args = { os.pullEvent("char") } if args[1] == "char" then if args[2] == "1" then coroutine.resume(mathsco) elseif args[2] == "2" then coroutine.resume(calcco) end end end end parent = coroutine.create(main()) mathsco = coroutine.create(maths()) calcco = coroutine.create(calc()) main()
Edited by DannySMc, 02 March 2015 - 11:15 PM.
#11
Posted 03 March 2015 - 02:57 AM
function os.pullEventRaw( sFilter ) return coroutine.yield( sFilter ) end function os.pullEvent( sFilter ) local eventData = { os.pullEventRaw( sFilter ) } if eventData[1] == "terminate" then error( "Terminated", 0 ) end return unpack( eventData ) end
#12
Posted 03 March 2015 - 09:13 AM
Bomb Bloke, on 03 March 2015 - 02:57 AM, said:
function os.pullEventRaw( sFilter ) return coroutine.yield( sFilter ) end function os.pullEvent( sFilter ) local eventData = { os.pullEventRaw( sFilter ) } if eventData[1] == "terminate" then error( "Terminated", 0 ) end return unpack( eventData ) end
I know this, but why does the code I posted not work? Thanks
#13
Posted 03 March 2015 - 10:22 AM
mathsco = coroutine.create(maths())
... to this sort of thing:
mathsco = coroutine.create(maths)
You also seem to be thinking that this:
coroutine.yield()
... will break out of your functions in a way that this:
local args = { os.pullEvent("char") }
... won't. However, both coroutine.yield() and os.pullEvent() will yield, because os.pullEvent() calls coroutine.yield() - there's very little difference between the two.
And then there's the matter of passing event data back into your coroutines when you resume them, and figuring out when it's time not to resume them...
Long story short, you need to further your understanding of how coroutines work before you can start writing this sort of code. Your current attempt can't simply be fixed by altering a couple of lines.
I suggest going back to the tutorial Lignum linked you to, and asking questions about any specific parts you don't understand. Once you feel you're familiar with the subject material, read the source code of the parallel API until that makes sense to you too. If you want an example of how you might further build that sort of logic into an OS, consider reading the source of the multishell script, too. From there, you'll have a much better foundation of knowledge from which to start writing your own code.
#14
Posted 03 March 2015 - 10:41 AM
Bomb Bloke, on 03 March 2015 - 10:22 AM, said:
mathsco = coroutine.create(maths())
... to this sort of thing:
mathsco = coroutine.create(maths)
You also seem to be thinking that this:
coroutine.yield()
... will break out of your functions in a way that this:
local args = { os.pullEvent("char") }
... won't. However, both coroutine.yield() and os.pullEvent() will yield, because os.pullEvent() calls coroutine.yield() - there's very little difference between the two.
And then there's the matter of passing event data back into your coroutines when you resume them, and figuring out when it's time not to resume them...
Long story short, you need to further your understanding of how coroutines work before you can start writing this sort of code. Your current attempt can't simply be fixed by altering a couple of lines.
I suggest going back to the tutorial Lignum linked you to, and asking questions about any specific parts you don't understand. Once you feel you're familiar with the subject material, read the source code of the parallel API until that makes sense to you too. If you want an example of how you might further build that sort of logic into an OS, consider reading the source of the multishell script, too. From there, you'll have a much better foundation of knowledge from which to start writing your own code.
Okay please do me one favor, will someone write a script that will be a menu that I can switch between two coroutines? as this is what is getting me and I need to see it in action... thanks in advance. I have looked at the tutorial multiple times, but can't seem to understand how it works...
On some other research, how does this parallel api work? will this allow me to make a simple menu? and run the coroutines? or?
#15
Posted 03 March 2015 - 10:54 AM
But read the parallel API first. It's a far simpler coroutine manager which takes a list of functions, rigs them up as coroutines and resumes each in turn over and over again until either one dies (when calling parallel.waitForAny), or until they all die (when running parallel.waitForAll). Take note of the way in which it uses the "filters" to work out which events should be used to resume which coroutines, the way in which it passes that event data on to resumed coroutines, and the way it handles dead coroutines.
#16
Posted 03 March 2015 - 11:21 AM
Bomb Bloke, on 03 March 2015 - 10:54 AM, said:
But read the parallel API first. It's a far simpler coroutine manager which takes a list of functions, rigs them up as coroutines and resumes each in turn over and over again until either one dies (when calling parallel.waitForAny), or until they all die (when running parallel.waitForAll). Take note of the way in which it uses the "filters" to work out which events should be used to resume which coroutines, the way in which it passes that event data on to resumed coroutines, and the way it handles dead coroutines.
Okay on that, how do you use these filters? I have had a read through it, just wondered how you would run an event? then wait? Now it sounds silly but I want to make a new OS, of course this one is for personal use but at the moment it won't be over the top advanced it is just to use the coroutines, like I need to figure out how to run a program then stop?
My idea: (it is gonna be basic, I just need to make sure it can handle the drawing from my api still):
I have a desktop:
1. When I click an icon for example calculator, it will run the program and add it to the taskbar.
2. then I can click home to go back, but the calculator program is halted, but when I click the calculator button in the taskbar i will be able to resume where I was, whether that being while typing or while it is waiting for an event (os.pullEvent()).
3. Then I can go back to the home screen and run another app, example worm, I can then click this and it will open it up and run it while adding it to the taskbar.
4. I should be able to switch between both apps and still be able to access the desktop
5. If the calculator ever stops running or I want to exit I can press say an X button that will delete the entry and stop the program/window and discard it?
Like windows.
I get it won't still be running but something that will allow me to switch between tasks and it will always be there.. wherever I left off.
I thought maybe using multiple windows? but if so how would I use the taskbar to redirect me back to the window and redraw the windows contents? All these apps are functions in my main os file? so i could be like run(functioncalculator()) etc.
Also if I have an app, how could I run a file in a new window? opening up the files contents and running it or?
If possible could you help me with this, code would be helpful so I can see how it done, so I can implement it myself because at the moment, I don't know where to start and when i say I am struggling to get my head around it you say read another link and this link still doesn't help, if possible I need examples, thanks again though as this is a big help!
Edited by DannySMc, 03 March 2015 - 11:22 AM.
#18
Posted 04 March 2015 - 01:11 AM
DannySMc, on 03 March 2015 - 11:21 AM, said:
Just saying "you don't get it" doesn't get us anywhere. Go back to the tutorial, and if you encounter a part you don't understand, point out the segment and I can rephrase it for you.
Likewise, the parallel API is a perfectly good code example. Don't understand what a given line is doing? Then quote out the first line that's giving you trouble, and it can be explained to you - etc until you get it.
#19
Posted 04 March 2015 - 09:12 AM
Bomb Bloke, on 04 March 2015 - 01:11 AM, said:
DannySMc, on 03 March 2015 - 11:21 AM, said:
Just saying "you don't get it" doesn't get us anywhere. Go back to the tutorial, and if you encounter a part you don't understand, point out the segment and I can rephrase it for you.
Likewise, the parallel API is a perfectly good code example. Don't understand what a given line is doing? Then quote out the first line that's giving you trouble, and it can be explained to you - etc until you get it.
Okay will have a try, I guess when I say I don't get it I mean, someone could so kind as to write a in-depth way of making the menu system I need, as it will be a lot more help, because I get the examples but none of them explain what I need it for...
1 user(s) are reading this topic
0 members, 1 guests, 0 anonymous users