Mike: Kudos to Spencer for a nice bit of code. Unless I'm reading it wrong, it does exactly the opposite of what I need: the main Forkable blocks until all of its children have finished. As for
...solace in programming as if the memory leaks and performance issues don't exist and I get more real work done this way.
Trust me -- I am NOT one to do "premature optimization". Rather, I was forced find a real solution once I realized I was consistently filling up memory during live performances. (Do you know how long it takes ChucK to respond even to ^C when that happens? The rest of the band was through a verse and the final chorus before I could regain control of my laptop!) I'll explain my approach in the next mail... - Rob On 8 Jun 2009, at 12:40, mike clemow wrote:
Hey Robert,
... The problem with killing the thread is that you leak 88K with each thread (!!!).
Normally, I feel like I'm the guy complaining about this kind of thing. ;-) I've decided that, despite the memory and performance issues surrounding shreds, sporking them, & cetera, I have decided that the ChucKian way of solving these types of problems is better than trying to program around them in ChucK. Programming around ChucK's issues in any other language would not be terribly hard, but in ChucK, it is hard. The thing is that ChucK provides a way of doing this stuff in a small amount of code and it takes an amount of code multiple orders of magnitude larger to solve the same problem in an performance/memory-optimized way.
The attached piece of code is something that Spencer Salazar whipped up for me one day in response to my gripe about shreds dying without finishing. It combines the idea of a shred and an event and I've based a lot of my frameworks around this one piece of code (thank you Spencer!). To use it, you subclass it and override the run() method with your sporkable shred code, instantiate your subclass and spawn the shred with yourForkable.start(). It would not be difficult to subclass this in such a way as to incorporate the concept of "wait for a signal (e.g. event.broadcast()) OR for a specific time to elapse, whichever comes first." Or it might be that your code wouldn't need such a thing, if you use this--I honestly don't know.
While this implementation doesn't explicitly reuse shreds, I have found solace in programming as if the memory leaks and performance issues don't exist and I get more real work done this way. One day, these problems will no longer exist and all our code will run much smoother. Until then, I've used this code as a basis for a granular synthesis implementation in which every grain is at least one (if not more) shred(s) and there's still a lot it can do before it breaks. I've tried programming around these issues, however, and I end up with code I can't even read, let alone understand or debug.
It's like there's a path-of-least-resistance that ChucK's system provides. Yes, if you travel that path you will run into certain issues, however, if you don't travel that path, you might as well be using something else, because you're missing out on the revolution that this path represents.
This is just my 2 cents.
_mike
On Mon, Jun 8, 2009 at 1:59 PM, dan trueman
wrote: jah, i've requested something like this before:
myEvent || 1::minute => now; //time advances to whichever comes first....
i've programmed around it using secondary timing shreds, but it would be much nicer to be able to do something like the above...
dt
On Jun 8, 2009, at 1:53 PM, Robert Poor wrote:
Gang:
In real-time music making, sometimes you want to wait for a signal (e.g. event.broadcast()) OR for a specific time to elapse, whichever comes first. I've implemented ways to do this, but I'm not really satisfied with the code.
Here's the problem: Lets say that your music is slaved to a metronome, and the metronome is allowed to change speed. You want your music to stay sync'd to the metronome. If you simply do: now + (1/tempo)::second => time next_beat; next_beat => now; play_note(); you'll be in trouble if the metronome speeds up while you're waiting: your note will be late. The fundamental problem is that once you execute "next_beat => now;", you're committed to waiting and there's now way to break out of it, short of killing the thread. The problem with killing the thread is that you leak 88K with each thread (!!!).
So here's the programming challenge: how would you implement a "wait for signal with timeout" that will block until it gets a signal OR a specified time has elapsed? Since each thread costs 88K in non-reclaimed memory, you may create threads, but your solution must re-use them.
As I said, I have implementations which I'm happy to share, but I'd like to see how you would do this first. Most of all, this is likely to turn into a feature request for the next version of ChucK.
- Rob _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users -- http://michaelclemow.com http://semiotech.org
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users