Help with pre-emptive multithreading
Basically I've been looking into integrating multiple scripts into a game engine. I've used my own basic command scripts in the past, and divided up execution time between scripts by doing one line at a time. Recently I've looked into the flexibility of using more advanced scripting languages such as Lua. Unfortunately, Lua seems to require the scripts to actually make a yield command, which doesn't seem ideal. What I'm looking for is a method of requesting a script to either execute one line at a time on demand, or execute for a limited amount of time, or automatically divide CPU time between multiple scripts in-between frames. I'm not really bothered about which language I use, but whichever method would be most suitable, and not too much hassle to implement. Any ideas? Thanks.
Actually cooperative multitasking is a lot more sensible than you think.
Ok, it got a bad press from things like Windows 3 and Macos < 10, but it's really ideal. Sensible operating systems with well controlled tasks which used it rarely had problems (Netware, anyone?)
The only reason we need preemptive multitasking is because our programs don't always cooperate.
If you wrote all the scripts yourself, you know that they're going to yield in ample time.
Specificially, if you have scripts for controlling (for example) NPCs, these will usually look like:
Those subroutines themselves, will all be of the basic form:
It is this second part "wait for it to become complete" which will do the yielding.
Your script need not explicitly yield anywhere, as long as it's always going to be in a loop calling something which always yields. This is not difficult to achieve.
Then in your native code, you can have something which checks whether the current action is complete, and if it is, calls resume() on the coroutine which called yield().
I've tested this idea and it seems to work fine.
Mark
Ok, it got a bad press from things like Windows 3 and Macos < 10, but it's really ideal. Sensible operating systems with well controlled tasks which used it rarely had problems (Netware, anyone?)
The only reason we need preemptive multitasking is because our programs don't always cooperate.
If you wrote all the scripts yourself, you know that they're going to yield in ample time.
Specificially, if you have scripts for controlling (for example) NPCs, these will usually look like:
// NPC code for NPC "bob"get out of bed;walk to door;open door;leave; close door;go to field;until (hometime) { work in field;}// etc
Those subroutines themselves, will all be of the basic form:
Trigger the beginning of some action;wait for it to become complete;
It is this second part "wait for it to become complete" which will do the yielding.
Your script need not explicitly yield anywhere, as long as it's always going to be in a loop calling something which always yields. This is not difficult to achieve.
Then in your native code, you can have something which checks whether the current action is complete, and if it is, calls resume() on the coroutine which called yield().
I've tested this idea and it seems to work fine.
Mark
Thanks!
When reading the Lua manual, I had only noticed the functions to use yield and resume from within the script. Now I've noticed that there are equivalent functions that can be used with the API from within C.
When reading the Lua manual, I had only noticed the functions to use yield and resume from within the script. Now I've noticed that there are equivalent functions that can be used with the API from within C.
You can't yield from the middle of C code. But I believe you can yield from a C function called from lua, as it returns.
You can of course resume coroutines from inside C code.
To make things easier, in my example I explicitly used yield() in the lua code. You'd do this in your library subroutines though, not in your NPC code.
Here is my code. This makes the NPC ("me") go to 42,99. walkTo() is a native (C++) method on the "me" object. hasArrived() returns a boolean.
Mark
You can of course resume coroutines from inside C code.
To make things easier, in my example I explicitly used yield() in the lua code. You'd do this in your library subroutines though, not in your NPC code.
Here is my code. This makes the NPC ("me") go to 42,99. walkTo() is a native (C++) method on the "me" object. hasArrived() returns a boolean.
function actions(me) me:walkTo(42,99) while (not me:hasArrived()) do print("Not there yet") coroutine.yield() end print("Yay, got there")end
Mark
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement