File: Thread.sc

package info (click to toggle)
supercollider 1%3A3.4.5-1wheezy1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 26,972 kB
  • sloc: cpp: 116,645; lisp: 64,914; ansic: 10,725; python: 3,548; perl: 766; ruby: 487; sh: 152; makefile: 117; xml: 13
file content (137 lines) | stat: -rw-r--r-- 3,476 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// you must not make any change at all to the order or number of
// instance variables in these classes!
// You should also not muck with the contents of the instance
// variables unless you are sure you know what you are doing.
// You may add methods.

// Thread inherits from Stream for the benefit of its subclass Routine which can
// behave like a Stream. Thread itself is not used like a Stream.

Thread : Stream {
	var <state=0, func, stack, method, block, frame, ip=0, sp=0;
	var numpop=0, receiver, numArgsPushed=0;
	var parent, terminalValue;
	var <primitiveError=0, <primitiveIndex=0, randData=0;
	var <beats=0.0, <seconds=0.0, <clock, <nextBeat, <>endBeat, <>endValue;
	var environment;
	var <>exceptionHandler;
	var <executingPath, <oldExecutingPath;

	*new { arg func, stackSize=512;
		^super.new.init(func, stackSize)
	}
	init { arg argFunc, argStackSize=512;
		_Thread_Init
		^this.primitiveFailed
	}
	copy { ^this } // sorry cannot copy

	clock_ { arg inClock;
		clock = inClock;
		beats = clock.secs2beats(seconds);
	}
	seconds_ { arg inSeconds; seconds = inSeconds; beats = clock.secs2beats(inSeconds); }
	beats_ { arg inBeats; beats = inBeats; seconds = clock.beats2secs(inBeats); }
	isPlaying { ^state == 5 }

	randSeed_ { arg seed;
		// You supply an integer seed.
		// This method creates a new state vector and stores it in randData.
		// A state vector is an Int32Array of three 32 bit words.
		// SuperCollider uses the taus88 random number generator which has a
		// period of 2**88, and passes all standard statistical tests.
		// Normally Threads inherit the randData state vector from the Thread that created it.
		_Thread_RandSeed
		^this.primitiveFailed;
	}
	randData_ { arg data;
		_Thread_SetRandData
		^this.primitiveFailed;
	}
	randData {
		_Thread_GetRandData
	}
	failedPrimitiveName { _PrimName }

	handleError { arg error;
		(exceptionHandler ? parent).handleError(error)
	}

	// these make Thread act like an Object not like Stream.
	next { ^this }
	value { ^this }
	valueArray { ^this }

	*primitiveError { _PrimitiveError }
	*primitiveErrorString { _PrimitiveErrorString; }

	storeOn { arg stream; stream << "nil"; }
	archiveAsCompileString { ^true }
	checkCanArchive { "cannot archive Threads".warn }
}

Routine : Thread {

	*run { arg func, stackSize=64, clock, quant=0;
		var routine = super.new(func, stackSize);
		^routine.play(clock ? SystemClock, quant);
	}

	// resume, next, value, run are synonyms
	next { arg inval;
		_RoutineResume
		^this.primitiveFailed
	}
	value { arg inval;
		_RoutineResume
		^this.primitiveFailed
	}
	resume { arg inval;
		_RoutineResume
		^this.primitiveFailed
	}
	run { arg inval;
		_RoutineResume
		^this.primitiveFailed
	}

	valueArray { arg inval;
		^this.value(inval)
	}

	reset {
		_RoutineReset
		^this.primitiveFailed
	}
		// the _RoutineStop primitive can't stop the currently running Routine
		// but a user should be able to use .stop anywhere
	stop {
		if(this === thisThread) { nil.alwaysYield }
			{ this.prStop };
	}
	prStop {
		_RoutineStop
		^this.primitiveFailed
	}

	p { ^Prout(func) }

	storeArgs { ^[func] }
	storeOn { arg stream;
		stream << this.class.name;
		this.storeParamsOn(stream);
		this.storeModifiersOn(stream);
	}

	// PRIVATE
	awake { arg inBeats, inSeconds, inClock;
		var temp = inBeats; // prevent optimization

		^this.next(inBeats)
	}
	prStart { arg inval;
		func.value(inval);
		// if the user's function returns then always yield nil
		nil.alwaysYield;
	}
}