Tasks

As promised on the page about Fork, I'm going to explain some more about tasks here.

Each program when run has its own task id number to distinguish it from other code being run at the same time. If you have any programs that suspend or fork, you can see them by typing @forked. (gc) On GondolinCores, this command is aliased to @ps as well - after the Unix command 'ps'.
In this display the first column, headed Queue ID, is the task id number for the program. This number is unique among the currently running tasks, but will not be over the duration of the running of the game.

To get this id number from inside your program, the function task_id() is the one to use. It will return the task id number, so:

id = task_id();
To get the id of a fork is a little different if you want to have access to it in the main body. To do this we put the variable we want to store it in after the 'fork' but before the brackets for it.
fork id (2)
...
endfork
This would store the task id of the newly created task in the variable id so that it could be used after the endfork. But...! Doesn't the (2) mean that the fork starts after 2 seconds? This is not strictly true. The new process is started instantly - but the code inside it doesn't start until 2 seconds have elapsed. You can think of it as a more compact version of:
fork id (0)
  suspend 2;
  ...
endfork
To get the task id of the fork inside the fork, simply use task_id() in the fork block.

Okay, so we have this id number. It's not very useful unless we can do something with it. There are two main things that we can do with it - we can kill it off, or we can tell a task that has suspended to start up again.


kill_task()

Sometimes you'll want to kill a program dead in its tracks from outside the code. For example if you write some code that by mistake goes into a never ending loop. For this, you can use the @kill command. However if you want to do it automatically in code, here's how.
First you need the id of the task you want to kill, as above. Then it's a simple matter of:

kill_task(id);

resume()

Resume is almost the opposite of kill_task(), but works on tasks that have suspended. Resume will stop the suspend and resume the execution of the task immediately. The function takes one argument, like kill_task, the id of the task to be resumed. So simply:

resume(id);

Using kill_task() and resume()

Here's an example of when kill_task and resume would be useful. It's a further extension of stroking the cat.
If you wanted the cat to do something else for a while until someone strokes it again, you could do something along the following lines:

First add a property to the cat called 'idle_process' with the default value of 0. We're going to use this to store the task id of the stroke command. Say for example we want the cat to nuzzle the player after 30 seconds looking for more stroking, unless they've stroked it again in the intervening time.


... do the current stroke code ...

if (this.idle_process != 0 && $code_utils:task_valid(this.idle_process))
  kill_task(this.idle_process);
endif
fork id (30)
  this.location:announce_all(this:titlec(), " rubs up against " player:title(), "'s leg, looking for more attention.");
  this.idle_process = 0;
endfork
this.idle_process = id;
We assign the id of the fork to the 'idle_process' property so that we can use it the next time the cat is stroked - remember that variables don't carry over between times that the command is called. First we do the current stroke code. Then we check if there's an idling cat process, if there is we kill it. Then we start a new process that will wait for 30 seconds and announce the cat rubbing up against the player. This could equally be done just by suspending for 30 seconds instead of forking. After that we put 0 into the idle_process as the task has finished running and there's nothing left to kill.