Why you should avoid processes
Author |
Message |
Insectoid
|
Posted: Wed Feb 03, 2016 9:49 am Post subject: Why you should avoid processes |
|
|
Inevitably in your Turing career, you're going to come across processes. You're going to think, wow! A really easy way to do two things at the same time! This will make my games a lot simpler to code! But processes are evil things that cause high school compsci students to lose their minds.
Look at the following piece of code: Turing: | loop
a := 0
count + = 1
delay (7)
if a = 0 then
put count. .
put " Boo!"
end if
exit when a not= 0
end loop |
Pretty basic stuff right? This loop should run forever. And it does. But what if it's part of a bigger project, and somewhere, that project contains this code: Turing: | process p
delay (1100)
a := 1
end p
fork p |
For your sake, here's both bits combined: Turing: | var a : int
var count : int := 0
process p
delay (1100)
a := 1
end p
fork p
loop
a := 0
count + = 1
delay (7)
if a = 0 then
put count. .
put " Boo!"
end if
exit when a not= 0
end loop
put "Ah!"
|
What do you think this code will do? It looks to me like it'll output "Boo!" every 7 ms, for 1100ms (or 1.1 seconds). Sounds right to me. Why don't you try running it a few times?
Did it run as expected? I bet not. For me, it usually ran between 65 and 67 times, but sometimes it ran up into the thousands before it quit! I dunno about you, but I like my programs to be predictable. Why does it have seemingly random behaviour when I never told it to do anything at random?
The reason is that processes do not run at the same time. They take turns, like a time-share condo in Aspen. Process A runs for a few ms, then process B runs for a few ms. This means either process can pause in the middle of execution and stop while another process runs. Then it starts back up where it left off. In my example, the program will only exit if the loop pauses during the 7 ms delay, and if process p manages to execute a := 1 in the few ms it's allotted. On my computer, that typically happened around the 66th iteration of the loop, but sometimes it missed that window and then ran on for thousands of iterations before the magic happened.
This is pretty easy to debug in a tiny program like this, but what if the program is a thousand lines long spread over ten files? The loop makes no reference to the process. There is nothing to tell you where a is being changed from 0 to 1. There are no clues to say what's happening. If you don't already know that process p exists, you can't solve this bug.
I have seen people write complicated games where the AI, the collision detection, the win detection, the art, and more is all controlled by processes. Those games were so broken they often crashed after a few minutes. The code looked fine. The collision detection code what correct. The AI was smart. Everything looked right. But the score counter was still wrong. The AI went in the wrong direction. The player could move through walls. Sometimes it worked, sometimes it didn't. Over time, more things broke, as more and more variables fell out of sync. These games were fundamentally broken and there was no way to fix them short of a complete restructuring to completely remove processes.
So how do you do things simultaneously without processes? Well, you don't. Here is how I fixed my example above:
code: | var a : int
var count : int := 0
loop
a := 0
count += 1
delay (7)
if Time.Elapsed >= 1100 then
a := 1
end if
if a = 0 then
put count..
put " Boo!"
end if
exit when a not= 0
end loop
put "Ah!"
|
Now there are no processes. The program will run for 1100ms, every time (actually more like 1101-1110, depending on how fast your computer is, but the point is it's consistent). It will never run up into the thousands. If something IS wrong, we know exactly where the variable a is changed.
If you're unsure how to write your game without using processes, look at some game tutorials on this site, or look at the code of submitted games. |
|
|
|
|
|
Sponsor Sponsor
|
|
|
|
|