Killing thread from without
Is it possible to kill a thread by saving a reference and calling exit() (or something) on that reference? Are there any means by which a created thread can be manipulated from without it by its reference? On a keyboard, I want a generator to be disconnected first some time after a key has been released - otherwise the sound will be truncated. How long depends on the generator, so I want to be able to set it arbitrarily. Then the problem is when the key is depressed again before this waiting time for disconnect has elapsed. One way to fix it is to let the thread check if the key has been depressed again, say by looking at the key down times, and if so, just skip the disconnect. But in order to avoid threads hanging around, it would be more logically to kill off the old one when the key is depressed again, as it is not needed anymore. So then write this function: BeeThree s[13][5]; // Sound generator for key coordinates x, y. ... fun void schedule_note_disconnect(int x, int y, dur t) { t => now; s[x][y] =< r; } When a key with coordinates x, y is released, schedule a disconnect: Shred @ note_disconnect[13][5]; ... 1 => s[x][y].noteOff; spork ~ schedule_note_disconnect(x, y, 1100::ms) @=> note_disconnect[x][y]; Then, when a key is depressed, I want to cheer it up using: if (note_disconnect[x][y] != null) note_disconnect[x][y].exit(); // Connect, set frequency and note on. However, it is easy to see that this exit(), though syntactically legal, does not affect the thread at all. So in the example above, a long note following one (on the same key) shorter than 1100::ms will be cut off. Hans
2009/4/21 Hans Aberg
Is it possible to kill a thread by saving a reference and calling exit() (or something) on that reference? Are there any means by which a created thread can be manipulated from without it by its reference?
Like this? fun void foo() { while(1) { <<<"beep">>>; second => now; } } spork ~foo() @=> Shred bar; 3::second => now; bar.exit(); second => now; <<<"bye">>>; Sadly there is currently a bug when we define a Shred object and later assign a actual shred to it; this will crash ChucK. This bug was likely caused by the last update which attempted to clean up the relationship between Shred objects and actual running processes (this wasn't always a very clear relationship). You can also have the Shred report it's number using me.id() inside that shred and set Machine.remove(int id ) loose on that. If this crashing bug bothers you (and it likely will) you can use this construct to get a shred's id number while sporking it; <<<(spork ~foo()).id()>>>; This integer can then be used with Machine.remove() to remove the shred. There are more illustrations in /examples/shred/ I think that should get you out of trouble? I can't recommend the /examples/ directory highly enough as a resource. Yours, Kas.
On 21 Apr 2009, at 21:32, Kassen wrote:
Like this?
fun void foo() { while(1) { <<<"beep">>>; second => now; } }
spork ~foo() @=> Shred bar;
3::second => now;
bar.exit(); second => now; <<<"bye">>>;
I think that tried that one, and it didn't work. Possibly because it gets stuck in <delay> => now; - your example allows jumping out of it in the 'while-loop.
Sadly there is currently a bug when we define a Shred object and later assign a actual shred to it; this will crash ChucK. This bug was likely caused by the last update which attempted to clean up the relationship between Shred objects and actual running processes (this wasn't always a very clear relationship).
I didn't try that one (I think) - I used references @=>, both in an array, and as a single global variable. exit() on such a reference while the thread was stuck in '<delay> => now' didn't work.
You can also have the Shred report it's number using me.id() inside that shred and set Machine.remove(int id ) loose on that.
If this crashing bug bothers you (and it likely will) you can use this construct to get a shred's id number while sporking it; <<<(spork ~foo()).id()>>>;
This integer can then be used with Machine.remove() to remove the shred.
So this is perhaps what I should try, though using exit() on the thread.
There are more illustrations in /examples/shred/
I think that should get you out of trouble? I can't recommend the / examples/ directory highly enough as a resource.
I grepped 'exit()' on the whole examples directory, but all finds were 'my.exit()', so it did not seem to apply. Hans
On 21 Apr 2009, at 21:32, Kassen wrote:
You can also have the Shred report it's number using me.id() inside that shred and set Machine.remove(int id ) loose on that.
One can replace the foo.exit() by: if (foo != null) Machine.remove(foo.id()); Then the reference is not set to null when it is killed, so one needs to have: fun void bar(dur t) { t => now; s[x][y] =< r; null => foo; } So my use of exit() should have been correct. One problem is that one gets a lot of printouts: [chuck](VM): removing shred: 32 (spork~exp)... When using <<< ... >>>, printouts cause a slight delays, that at least on a slow machine may make fast keyboard playing impossible. Hans
On Apr 21, 2009, at 9:13 PM, Hans Aberg wrote:
Is it possible to kill a thread by saving a reference and calling exit() (or something) on that reference? Are there any means by which a created thread can be manipulated from without it by its reference?
On a keyboard, I want a generator to be disconnected first some time after a key has been released - otherwise the sound will be truncated. How long depends on the generator, so I want to be able to set it arbitrarily. Then the problem is when the key is depressed again before this waiting time for disconnect has elapsed. One way to fix it is to let the thread check if the key has been depressed again, say by looking at the key down times, and if so, just skip the disconnect.
If I understand this correctly, I would use an envelope for that. So when the key is pressed the envelope fires up, and when the key is released, the oscillator will stop at the end of the envelope's release time. You may want to have a look at a chuck template for polyphony I wrote a year ago for a workshop. You'll find it at http://www.lullcec.org/chuck/template_polyphony.ck . At that time it was working, not sure now. Be aware that envelope's release time is set quite long (1::second). hope it helps, eduard
On 23 Apr 2009, at 10:46, eduard aylon wrote:
Is it possible to kill a thread by saving a reference and calling exit() (or something) on that reference? Are there any means by which a created thread can be manipulated from without it by its reference?
On a keyboard, I want a generator to be disconnected first some time after a key has been released - otherwise the sound will be truncated. How long depends on the generator, so I want to be able to set it arbitrarily. Then the problem is when the key is depressed again before this waiting time for disconnect has elapsed. One way to fix it is to let the thread check if the key has been depressed again, say by looking at the key down times, and if so, just skip the disconnect.
If I understand this correctly, I would use an envelope for that. So when the key is pressed the envelope fires up, and when the key is released, the oscillator will stop at the end of the envelope's release time. You may want to have a look at a chuck template for polyphony I wrote a year ago for a workshop. You'll find it at http://www.lullcec.org/chuck/template_polyphony.ck . At that time it was working, not sure now. Be aware that envelope's release time is set quite long (1::second).
From what I can see from a quick look at your code, I do the same, i.e., setting a time for the generator to decay after the key is released. The problem is when a key is released and pressed again before the decay time has elapsed. Then, if the key controls the same generators, and the disconnect event is not cancelled, the note will be cut short. I could not see how you solved that problem. Do yo create a new generator every time the same key is pressed? I have one generator per key. This roughly corresponds to MIDI numbers, because E12 enharmonic equivalence does not apply. In view of the thread-kill problem, and that I haven't figured out how to schedule and cancel future events, I use: fun void noteoff(int x, int y, dur t) { note_on[x][y] => time t_my; 1 => s[x][y].noteOff; t => now; if ((note_on[x][y] == t_my) && s[x][y].isConnectedTo(r)) s[x][y] =< r; } It simply checks if the key has been pressed again, and then skips the disconnect - some other thread will handle that. Hans
participants (3)
-
eduard aylon
-
Hans Aberg
-
Kassen