Posted: Sat Feb 19, 2005 11:29 am Post subject: Why You Should Avoid Processes
For the somewhat new programmer, using processes may seem almost manditory. You may want to do two things simultaneously and immediately think, "I can use a process for that!" But when you think that, you're making a big mistake.
In Turing, processes are terrible. They should be avoided at all costs (really, the only time they should be used is for playing music, but Turing 4.0.5 makes it so we don't even need them for that).
"Why are processes so terrible," you ask? Well, take a look at the example in the help file:
Turing:
process greetings (word :string) loop put word
endloop end greetings
fork greetings ("Hi") fork greetings ("Ho")
Run it. After a second, stop it. You should see a very inconsistant pattern on the screen. This is because the processes execute at different (almost random, it seems) speeds. It's not as though greetings ("Hi") executes once, then greetings ("Ho") once, then once again for greetings ("Hi"), etc. No, Turing's processes don't work the way you want them to.
"But I don't care if they work at different rates!", you yell.
Aah, you should. Lets say we've got two objects, and we want to move them across the screen. object1 has a speed of 1, and object2 has a speed of 2. Both must travel the same distance. Using processes, object 2 will likely not reach its destination twice as fast as object1. Rather, it will reach its destination approximately twice as fast as object1. This may not seem like a big issue, but it is. You never know how your program is going to behave, because the processes run in a random fashion.
Actually I just discovered another bad thing about processes: you can't use "var" parameters. ie. you can't go
code:
process move (var foo : string)
We'll let Hacker Dan finish this for us:
Hacker Dan wrote:
Process can be good but you have to understand how they work and turing has limited conortl over them. Since turing has no way to set proity of a process all you know is that the code may run at some time. So baliky unless you got a dual CPU system a process will run lines of code in it at basicly random times durning the excution of your progame. If it dose not mater when they run then it could be good to use them but it gives you less conortl over things.
In conclusion, don't use processes. They are evil. If you choose to use them, fine, but you are only hurting your own program. You'll probably end up spending hours down the line reworking everything to eliminate the processes.
I'm no expert on this matter, but so many people have been trying to/using processes lately I felt something had to be done. Any elaboration on this matter, or more convincing/moral support, is welcome.
-Cervantes
Sponsor Sponsor
cycro1234
Posted: Sat Feb 19, 2005 12:21 pm Post subject: (No subject)
Wow, thanks for that tutorial!
But If I shouldn't use processes to make 2 things run at the same time, I use instead? Like, what if I'm making a game and I want the person to shoot and move at the same time. How will I work that out? Or what If i want to animate 2 objects at the same time doing different actions unrelated to each other.
Martin
Posted: Sat Feb 19, 2005 1:04 pm Post subject: (No subject)
No. Your main loop should look like this:
code:
loop
if up arrow pressed then
playery += 1
end if
if left arrow pressed then
playerx += 1
end if
if ...
...
end if
for i : 1 .. numBullets
updatebulletposition(i)
end for
drawScene %player, bullets, etc.
end loop
The absolute only time that you should ever use a process is when you are doing sound.
cycro1234
Posted: Sat Feb 19, 2005 1:08 pm Post subject: (No subject)
Ok. Thanks.
Cervantes
Posted: Sat Feb 19, 2005 1:31 pm Post subject: (No subject)
Basically, you stick it all in the same loop. As to how to do it (well, it's really easy, but if you're stuck thinking in terms of processes, it might be a little difficult), the easiest way to show you how is with examples.
cycro1234 wrote:
Like, what if I'm making a game and I want the person to shoot and move at the same time.
There's an easy one. Shooting and moving is the same, in that both rely on input from the keyboard (or mouse).
All you have to do is make your fire procedure. How you do that is related to your second question.
cycro1234 wrote:
Or what If i want to animate 2 objects at the same time doing different actions unrelated to each other.
There is always something that is related. Always. What is related is time. Just as my fingers move to type this, our solar system is hurtling around the Milky Way at 900 000km/h. We have two objects (my fingers, and the solar system) whose motions pretty well don't affect one another, but are nonetheless related through time. Every hour that my fingers move, the solar system travels 900 000km. Or, every hour that my fingers don't move, the solar system travels 900 000km. No matter what, the motions of the two objects are joined by time.
Because the motions are joined by time, we want to avoid using a process. Using a process would be like randomly accelerating time for one object, and slowing time for another. By using just one loop, however, we can keep time going at a constant pace.
Below you'll find three programs. The first is really all that I need to show how you do this without using processes. The second program is the same code, but much neater. The last uses many objects.
Turing:
View.Set("offscreenonly") var ballx :=0.0 var bally :=50.0 var ballvx :=2 var ballvy :=0.6
var starx :=50.0 var stary :=150.0 var starvx :=2.5 var starvy := -0.3
The next code takes the motion section (the ball.x += ball.vx etc. part) and sticks it into a procedure. Then it uses that procedure many times, for there are many more objects in this one.
Turing:
View.Set("offscreenonly") type obj : record
x :real
y :real
vx :real
vy :real endrecord
To recap: don't use processes, because doing so means you're screwing with time. Use a single main loop. The concept is no different than using processes. You just have to keep your main loop structured nicely. (ie. keep all your drawing at the end, all your input at the beginning, and all your variable manipulation in the middle).
-Cervantes
Tony
Posted: Sat Feb 19, 2005 1:31 pm Post subject: (No subject)
I'd like to add that if both processes use the same global variable, the results will be disastrous.
You essensially throw your code flow into a blender, mix it up and say. "Here I have a bunch of lines of code. They are in no particular order. If the computer happens to pick the right order - the results will be as expected. Otherwise I have no idea what might happen"
cycro1234
Posted: Sat Feb 19, 2005 1:45 pm Post subject: (No subject)
Ok, thanks a lot for that guys! I get it a lot more now.
But if processes are so useless, why were they added in Turing? Only to make music run?
Cervantes
Posted: Sat Feb 19, 2005 3:33 pm Post subject: (No subject)
Processes (threads?) are not a feature of Turing alone. Many other languages have them, though I believe their processes actually work orderly, not randomly. I can only assume Holtsoft tried to give Turing what those other languages have. Boy did they fail...
Sponsor Sponsor
Flikerator
Posted: Sat Feb 19, 2005 6:00 pm Post subject: (No subject)
For my final project (Pong) I used like 6 forks. Ai, paddle, paddle2 (2 player), music, lives, and ball. I wouldn't do anything like that cause now I am not so nubish anymore.
I pulled a 90 out of my first year with that sort of programming lolz.
Quote:
the only time they should be used is for playing music, but Turing 4.0.5 makes it so we don't even need them for that
What do you mean, how do we play music without using a process? This will help greatly in Zombie Mass'Acres
rizzix
Posted: Sun Feb 20, 2005 12:40 am Post subject: (No subject)
hmm i dont get it.. what do u guys mean by random? the lines of code executed with the process code-block is random? (quite impossible) if so, never use processes. if not.. there is nothing wrong with the processes. they are just fine, just that you guys are not used to concurrent programming.
md
Posted: Sun Feb 20, 2005 1:17 am Post subject: (No subject)
Cervantes wrote:
Processes (threads?) are not a feature of Turing alone. Many other languages have them, though I believe their processes actually work orderly, not randomly. I can only assume Holtsoft tried to give Turing what those other languages have. Boy did they fail...
Threads (as processes are really known) are actually a feature of the OS (windows), or very low level code (linux can use kernel threads and user threads [i think], basically their only different in what does the schedualing). However your wrong in your assumption that they are run in an orderly fasion.
Say we have two threads, A and B. Thread A will be run for a given time (a very small ammount of time...), then thread B will be given a chance.
The problem is when unshedualed things happen, say a keystroke. The OS must then switch from the thread to the keyboard handling process which will then run until it is done or something else interupts it. Once the keyboard process is done the OS returns execution back to the next ready process (not nessarilly ours). The next time it gets arround to running our process it will probably run the next thread in the queue (which, again, will probably not be the one that was interupted).
Thus something as trivial as an interupt can cause any thread to lose some of it's execution time. And since interupts are generated by almost all hardware and at a fairly high rate, execution times are not perfectly balanced.
Of course modern threads can be prioritized, or blocked (set not to run), so in practice threads are actually are very usefull tool. Although I wouldn't recomend creating a lot of threads, as each thread adds overhead, and creating one for such a simple task as an animation is frivilous.
cycro1234
Posted: Tue Feb 22, 2005 4:55 pm Post subject: (No subject)
I have this code to shoot and move, but it's not working:
code:
View.Set ("offscreenonly")
var chars : array char of boolean
var x, y : int := 100
forward proc movement
proc shoot (var y : int)
loop
y := y + 1
drawoval (x+35,y-1,10,10,0)
drawoval (x+35,y,10,10,7)
drawoval (x-35,y-1,10,10,0)
drawoval (x-35,y,10,10,7)
View.Update
exit when y + 20 > maxy
movement
end loop
end shoot
body proc movement
loop
Input.KeyDown (chars)
if chars (KEY_UP_ARROW) and y + 64 < maxy then
y := y + 1
elsif chars (KEY_DOWN_ARROW) and y > 0 then
y := y - 1
elsif chars (KEY_LEFT_ARROW) and x > 0 then
x := x - 1
elsif chars (KEY_RIGHT_ARROW) and x + 64 < maxx then
x := x + 1
elsif chars (KEY_CTRL) then
shoot (y)
end if
cls
drawfilloval (x,y,20,20,7)
View.Update
end loop
end movement
loop
movement
end loop
Hold ctrl to shoot and move with arrow keys.
I thought that if I called movement in the procedure shoot then I could shoot and move at the same time. It doesn't work! The y value that I need for the bullet interferes wit the y value of the position of the circle. After shooting the bullets, the y value of them is stored and is used to draw the cirle in a place i do not need. Any ideas how to fix?
jamonathin
Posted: Tue Feb 22, 2005 8:13 pm Post subject: (No subject)
You have to give the bullet's their own variables. 'x' and 'y' are already used by the "shooter" and so by adding to the y-value, you're changing where the shooter is. This is what i came up with. .
code:
View.Set ("offscreenonly")
var chars : array char of boolean
var x, y, bullety, bulletx : int := 100
var shot : int := 0
forward proc movement
proc shoot
loop
shot := 1
bullety += 1
exit when bullety + 20 > maxy
movement
end loop
shot := 0
end shoot
body proc movement
Input.KeyDown (chars)
if chars (KEY_UP_ARROW) and y + 64 < maxy then
y := y + 1
elsif chars (KEY_DOWN_ARROW) and y > 0 then
y := y - 1
elsif chars (KEY_LEFT_ARROW) and x > 0 then
x := x - 1
elsif chars (KEY_RIGHT_ARROW) and x + 64 < maxx then
x := x + 1
end if
if chars (KEY_CTRL) and shot = 0 then
bullety := y
bulletx := x
shoot
end if
cls
if shot = 1 then
drawoval (bulletx + 35, bullety - 1, 10, 10, 0)
drawoval (bulletx + 35, bullety, 10, 10, 7)
drawoval (bulletx - 35, bullety - 1, 10, 10, 0)
drawoval (bulletx - 35, bullety, 10, 10, 7)
end if
drawfilloval (x, y, 20, 20, 7)
View.Update
end movement
loop
movement
end loop
The shooter moves a little slower while the bullets are being fired however. If you want, you can have a variable represent the displacement of the shoot (y + 1 to y + dif), and when the ball is being fired, dif will equal 2, but outside the loop, dif will equal 1, your choice.
cycro1234
Posted: Tue Feb 22, 2005 10:06 pm Post subject: (No subject)
K got it. Thx.
HyperFlexed
Posted: Wed Feb 23, 2005 10:04 pm Post subject: (No subject)
Never looked into it but I believe Turing has a way to set the priorities of processes. I must agree though, many people failed my compsci class because they used them innapropriately.
One guy made this game where red and black blocks float across the screen and you gotta hit the red and avoid the black. Not only did he use processes, he made one process for each block rather than passsing in the values (I suppose it'd be redundant eather way).
The biggest thing to understand is a computer goes so fast, you don't have to worry to much about the order of how things are done. And if you are using View.Update and getting everything at once, your user won't get screwed, and your program will be alot faster for it.
that reminds me, I should post my final project. I made tetris, hehe.