Routine:
Filter:
Classes | Core > Kernel

Routine : Thread : Stream : AbstractFunction : Object

Functions that can return in the middle and then resume where they left off
Source: Thread.sc

Description

A Routine runs a Function and allows it to be suspended in the middle and be resumed again where it left off. This functionality is supported by the Routine's superclass Thread. Effectively, Routines can be used to implement co-routines as found in Scheme and some other languages.

A Routine is started the first time -next is called, which will run the Function from the beginning. It is suspended when it "yields" (using Object: -yield within the Function), and then resumed using -next again. When the Function returns, the Routine is considered stopped, and calling -next will have no effect - unless the Routine is reset using -reset, which will rewind the Function to the beginning. You can stop a Routine before its Function returns using -stop.

When a Routine is scheduled on a Clock (e.g. using -play), it will be started or resumed at the scheduled time. The value yielded by the Routine will be used as the time difference for rescheduling the Routine. (See -awake).

Since Routine inherits from Thread, it has its own associated logical time, etc. When a Routine is started or resumed, it becomes the current thread.

Routine also inherits from Stream, and thus shares its ability to be combined using math operations and "filtered".

Class Methods

Routine.new(func, stackSize: 512)

From superclass: Thread

Creates an instance of Routine, passing it the Function with code to run.

Arguments:

func

A Function with code for the Thread to run.

stackSize

Call stack size (an Integer).

Discussion:

The Function class provides its own shortcut method r that calls Routine.new, thus one can also write:

Inherited class methods

Undocumented class methods

Routine.run(func, stackSize, clock, quant)

Instance Methods

.next(inval)

This method performs differently according to the Routine's state:

thisThread : Since Routine inherits from Thread, it will become the current thread when it is started or resumed; i.e. thisThread used in the Routine Function will return the Routine.

Time: Just before next is called, thisThread points either to another Routine, or the top-level Thread. During the next call, this becomes the parent thread (see Thread: -parent). next then evaluates on the parent's clock, at the parent's logical time.

Synonyms for next are -value and -resume.

Returns:

  • Either the value that the Routine yields (the Object on which yield is called within the Routine Function),
  • ...or nil, if the Routine has stopped.

Discussion:

When a Routine is started by a call to this method (or one of its synonyms), the method's argument is passed on as the argument to the Routine Function:

After the Routine has yielded (it has been suspended at the point in its Function where yield is called on an Object), a call to this method (or its synonyms) resumes executing the Function and the argument to this method becomes the return value of yield. To access that value within the Function, you have to assign it to a variable - typically, the argument of the Function is reused:

Typically, a Routine yields multiple times, and each time the result of the yield is reassigning to the argument of its Function.

.value(inval)

Equivalent to -next.

.resume(inval)

Equivalent to -next.

.stop

Equivalent to the Routine Function reaching its end or returning: after this, the Routine will never run again (the -next method has no effect and returns nil), unless -reset is called.

.reset

Causes the Routine to start from the beginning next time -next is called.

Discussion:

If a Routine is stopped (its Function has returned or -stop has been called), it will never run again (the -next method has no effect and returns nil), unless this method is called.

A Routine cannot reset itself, except by calling Object: -yieldAndReset.

See also: Object: -yield, Object: -alwaysYield

.play(clock, quant)

From superclass: Stream

Schedules the Routine on the given Clock, at a time specified by quant. At that time, the Routine will wake up (by calling Routine: -awake), setting the clock and time and evaluating the Routine. If the Routine yields a number, this number of beats will be added to the current time and the Routine will be rescheduled. (This behavior is compatible with scheduling a Stream or a Function.)

Arguments:

clock

a Clock, TempoClock by default

quant

see the Quant helpfile

Discussion:

using Object: -idle within a routine, return values until this time is over. Time is measured relative to the thread's clock.

.reschedule(argClock, quant)

If a Routine is currently scheduled on a clock, it will be expected to "awake" at a specific time, on a specific clock. reschedule allows you to change to a different clock or to a later time.

Arguments:

argClock

The new clock on which to run the Routine. If nil, the routine's clock will not be changed. (Note: Currently incompatible with AppClock; rescheduling depends upon the method schedAbs, which AppClock does not implement.)

quant

A quantization specifier, identifying a time later than the next-scheduled time. If nil, the current value of nextBeat will be used.

Discussion:

.awake(inBeats, inSeconds, inClock)

This method is called by a Clock on which the Routine was scheduled when its scheduling time is up. It calls -next, passing on the scheduling time in beats as an argument. The value returned by next (the value yielded by the Routine) will in turn be returned by this method, thus determining the time which the Routine will be rescheduled for.

Arguments:

inBeats

The scheduling time in beats. This is equal to the current logical time (Thread: -beats).

inSeconds

The scheduling time in seconds. This is equal to the current logical time (Thread: -seconds).

inClock

The clock which awoke the Routine.

.p

Convert the routine to a (subclass of) Pattern.

Returns:

A Prout that (in response to asStream) acts as a generator of independent copies of the original routine (the receiver of p).

Discussion:

Any subclass of Pattern returns a Stream in response to asStream. However, the exact subclass of Stream returned depends on the class of the Pattern. In particular, a Prout returns a Routine in response to asStream. Thus, a way to make an independent copy of a Routine is to make a Prout from it with the method p, and then create a new Routine from this Prout. In the example immediately below, this second step is done explicitly by calling asStream, but in the context of passing arguments to other Patterns, this latter step usually happens automatically, as shown in later examples.

NOTE: New routines produced by .p.asStream run the original routine's function from the beginning. There is no copy of the internal state of the original routine, only its function is copied. On a related note, Routine.copy (inherited from Thread) does not create a new, separate Routine; it just returns the receiver.

The Routine method p is mostly useful in the context of using the result of Routine-returning expressions as arguments to Patterns, when the intent is to use the Routine's result as a pattern, i.e. multiple occurrences acting independently of each other.

In the following example, directly reusing the same Routine object twice in a Pseq fails to duplicate its output, because the first embedding fully consumes the routine's (non-nil) output.

Accessible instance variables

Routine inherits from Thread, which allows access to some of its state:

.beats

.beats = inBeats

From superclass: Thread

Returns:

The elapsed beats (logical time) of the routine. The beats do not proceed when the routine is not playing.

.seconds

.seconds = inSeconds

From superclass: Thread

Returns:

The elapsed seconds (logical time) of the routine. The seconds do not proceed when the routine is not playing, it is the converted beat value.

.clock

.clock = inClock

From superclass: Thread

Returns:

The thread's clock. If it has not played, it is the SystemClock.

Inherited instance methods

Undocumented instance methods

.fastgui(name: "routine")

From extension in /home/stefan/.local/share/SuperCollider/downloaded-quarks/wslib/wslib-classes/GUI/Extensions/extSynthdef-fastgui.sc

.prStart(inval)

.prStop

.run(inval)

.valueArray(inval)

Examples