/
ColdC/Functions/
ColdC/Structure/
<head><title>ColdC: Frames and Tasks</title></head>

<body>
<h1 align=center><a href="/ColdC/">ColdC</a>: Frames and Tasks</h1>
<hr>

<p>While a method is being executed it is called a <i>frame</i>.  The
frame is relevant only to the current method.  Each frame has a limited
amount of time that it can execute in, also known as <i>ticks</i>.  If
a frame runs out of ticks before it is finished executing, the
<code>~ticks</code> error is thrown.

<p>Multiple methods calling each other in succession is called a task.
Tasks usually originate from either a connection, a heartbeat, or by being
forked from another task.  There is no restriction on how long a task
can execute, other than that imposed upon each frame.

<p>It is possible to pause an executing frame and refresh the ticks it
has by calling the function <code><a href="/ColdC/Functions/pause.html">pause()</a></code>.  When this occurs the frame stops executing and it's task
is placed behind all other current tasks.  When all other current tasks
are completed executing the paused task will resume with a new tick pool.
This behavior is called <i>preempting</i>.

<p>If you are unsure about the amount of ticks left in a method, you can
call the function <code><a href="/ColdC/Functions/ticks_left.html">ticks_left()</a></code>.  Or, you can call <code><a href="/ColdC/Functions/refresh.html">refresh()</a></code> instead of <code>pause()</code>.  <code>refresh()</code> will
only preempt if the current frame is nearly out of ticks.

<p>You can also suspend a task indefinitely, by using the function
<code><a href="/ColdC/Functions/suspend.html">suspend()</a></code>.  The
function <code><a href="/ColdC/Functions/resume.html">resume()</a></code>
will resume a suspended task.  The function <code><a href="/ColdC/Functions/cancel.html">cancel()</a></code> will cancel a suspended task.

<p>An example of suspending a task is for reading an indefinite amount of
input from a connection.  Input arrives through the <var>parse</var> method
on an object (see <a href="/ColdC/networking.html">Networking</a>), which
we define as follows, assuming the object variables <var>reading</var>, 
<var>read</var>, <var>buffer</var> and <var>lines</var>.  <var>reading</var>
is used to store a boolean value of true or false, depending upon if we are
reading input or not.  <var>read</var> is used to store what we have already
read from the connection.  <var>buffer</var> is used to store incoming
information which is not yet parsable by the function
<var>buf_to_strings()</var> (i.e.  there is no carriage return yet). 
<var>lines</var> is used to buffer lines converted by
<var>buf_to_strings()</var> from the connection which we
have not parsed yet.  It is important to use an object variable for both
<var>buffer</var> and <var>lines</var>, because if the task suspends all
information stored in either variable would be suspended along with that
instance of the task.

<p><blockquote><pre>
driver method .parse() {
    arg incoming;
    var line;

    lines = buf_to_strings(buffer + incoming));
    buffer = lines[listlen(lines)];
    lines = delete(lines, listlen(lines));

    // now parse the lines
    for line in (buf_to_strings(incoming)) {
        if (reading) {
            if (line == ".")
                .done_reading();
            else
                read += [line];
        } else {
            .parse_line(line);
        }
    }
}
</blockquote></pre>

<p>We will not define the method <var>parse_line</var>, just assume that
it parses the line as a command.  When an object wishes to start reading
from the connection it calls the method <var>.read()</var> on the connection
object:

<p><blockquote><pre>
public method .read() {
    // reading just has to be true, so lets save space and store the task
    // id there as well, instead of storing it in another variable.
    reading = task_id();

    // make sure this is an empty list
    read = [];

    // suspend the task, have our return value be the return value of suspend
    // (which is whatever resume() sends)
    return suspend();
}
</pre></blockquote>

<p>When a period is found as the line being read, the connection is
done reading (the period is insignificant, you can terminate your reading
any way you desire), and the method <var>done_reading</var> is called:

<p><blockquote><pre>
protected method .done_reading() {
    var info, task;

    // get a local copy of what we read, and the task id
    info = read;
    task = reading;

    // reset the object variables first
    read = [];
    reading = 0;

    // resume the task, send what we read as the return value for suspend()
    resume(task, info);
}
</pre></blockquote>

<p>Now, all that has to happen to read input from a connection is to call
the method <var>.read()</var> on the connection object, and the input
read is returned from the method call.

<p>It is possible to set a task as <i>atomic</i>.  Atomic tasks cannot
be preempted or suspended.  If an attempt is made to preempt or suspend
an atomic task the error <code>~atomic</code> is thrown instead.  However,
calling <code>refresh()</code> while executing atomically will always
refresh the current frame's ticks.  A task's atomic state is toggled using
the function <code><a href="/ColdC/Functions/atomic.html">atomic()</a></code>.

<p><b>Note:</b> be very cautious when using atomic tasks.  Atomic tasks
can easilly disrupt the regular integrity of an online environment.  See
the section on <a href="security.html">Security</a>.

<hr size=4><p align=center><i>Last Modified on Feb 25 1996</i>
<br><i>Copyright &copy; 1995, 1996, Brandon Gillespie</i>
</body>