<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 © 1995, 1996, Brandon Gillespie</i> </body>