This note contains a coding tip, a feature request and a bug report. In that order. CODING TIP: Resource pools are a simple way to avoid memory allocation. This should be old hat to veteran coders, but I remember thinking this was a cool technique when I first saw it. This is important in embedded systems (that lack malloc()/free()) and also in ChucK (which doesn't GC heap-allocated objects). The concept is simple: you keep an array (a "pool") of available items. When you want an item, you take one out of the pool, or create one if the pool was empty. When you're done with the item, you just chuck it back in the pool for the next time someone wants it. The code is simple. Let's say you created some structure, like a NoteEvent, that you'll be using heavily in your ChucK code. By "heavily", I mean you'll be creating thousands of these every second: public class NoteEvent { float frequency; float commercial_potential; int makes_adults_complain; } How do you keep ChucK's memory from getting silted up? Use a resource pool. Here's the code. NoteEvent @ _noteEventPool[0]; fun NoteEvent allocateNoteEvent() { null @=> NoteEvent @ noteEvent; if ((_pool.size() => int size) > 0) { // pop a NoteEvent from the end of the _pool, if available _pool[size-1] @=> noteEvent; size-1 => _pool.size; } else { // the pool is empty, create a new one new NoteEvent @=> noteEvent; } return noteEvent; } fun void freeNoteEvent(NoteEvent @ noteEvent) { // push noteEvent onto the pool so it's available for the next // call to allocateNoteEvent(). _pool << noteEvent; } Call allocateNoteEvent() when you need a noteEvent, call freeNoteEvent() when you're done with it. You're responsible for freeing them when you're done with them -- it's not automatic -- but if you free each event that you allocate, ChucK will not allocate any memory above what' needed. FEATURE REQUEST As written, array's popBack() function has a void return. It would be nice if popBack() returned the element it removed, so we could write the code like this: fun NoteEvent allocateNoteEvent() { null @=> NoteEvent @ noteEvent; if (_pool.size() > 0) { _pool.popBack() @=> noteEvent; } else { new NoteEvent @=> noteEvent; } return noteEvent; } BUG REPORT This may be operator error rather than a bug, but the following code: fun Element allocateElement() { if ((_pool.size() => int size) > 0) { _pool[size-1] @=> Element @ element; size-1 => _pool.size; return element; } return new Element; } reports: chuck(20184,0xa018a830) malloc: *** error for object 0x5eb6e0: double free *** set a breakpoint in malloc_error_break to debug I think the problem may be in "return new Element" -- it may be trying to return the Element itself, rather than a reference to the Element. If that's the case, though, it seems like something that should be caught at compile time. - Rob
Rob; FEATURE REQUEST
As written, array's popBack() function has a void return. It would be nice if popBack() returned the element it removed, so we could write the code like this:
I agree with this, it's not clear to me why it doesn't do this already. Actually I thought it did but only worked correctly for primitives. I just tested and that turns out to be a mistake. I think it's clear that we need this and I hope it'll be addressed one when somebody goes over the series of bugs related to arrays and type; it can't be very hard, assuming the other existing issues will be addressed. Our arrays need some loving care.
BUG REPORT
This may be operator error rather than a bug, but the following code:
fun Element allocateElement() { if ((_pool.size() => int size) > 0) { _pool[size-1] @=> Element @ element; size-1 => _pool.size; return element; } return new Element; }
reports:
chuck(20184,0xa018a830) malloc: *** error for object 0x5eb6e0: double free *** set a breakpoint in malloc_error_break to debug
I think the problem may be in "return new Element" -- it may be trying to return the Element itself, rather than a reference to the Element. If that's the case, though, it seems like something that should be caught at compile time.
I suspect this is another case of the bits of the GC that are are already in there and occasionally collect things before they need to be collected. Until there is a new version I'm inclined to categorise anything related to more advanced operations on arrays involving no-primitive types on the "Clemow's bane" pile. First of all there is the issue that I think we are seeing here which involves the over-collection of things that aren't (yet) garbage, secondly there is the issue that if you do manage to get a item out of a array in a way like this ChucK will somehow lose track of what type it is at which point there will be issues of a extremely headache-inducing nature. Mike may be able to help you; I seem to remember him&me got something quite similar to this to work for some of his code but I forgot the details. The one thing my memory hasn't repressed is that the solution involved sprinkling the code with magical "@" signs, more or less at random :¬). I love ChucK but here be dragons. Yours, Kas.
Rob, Kas,
+1 on the popBack() feature request. But I would also like to add
some syntactic icing to the cake in the form of an inverse append
operator:
If this means "push":
myArray << 5;
then this should mean "popBack":
myArray >> int myInt;
after which:
<<< myInt >>>;
should print "5 (int)"
Consistency is king.
_mike
2009/4/12 Kassen
Rob;
FEATURE REQUEST
As written, array's popBack() function has a void return. It would be nice if popBack() returned the element it removed, so we could write the code like this:
I agree with this, it's not clear to me why it doesn't do this already. Actually I thought it did but only worked correctly for primitives. I just tested and that turns out to be a mistake.
I think it's clear that we need this and I hope it'll be addressed one when somebody goes over the series of bugs related to arrays and type; it can't be very hard, assuming the other existing issues will be addressed. Our arrays need some loving care.
BUG REPORT
This may be operator error rather than a bug, but the following code:
fun Element allocateElement() { if ((_pool.size() => int size) > 0) { _pool[size-1] @=> Element @ element; size-1 => _pool.size; return element; } return new Element; }
reports:
chuck(20184,0xa018a830) malloc: *** error for object 0x5eb6e0: double free *** set a breakpoint in malloc_error_break to debug
I think the problem may be in "return new Element" -- it may be trying to return the Element itself, rather than a reference to the Element. If that's the case, though, it seems like something that should be caught at compile time.
I suspect this is another case of the bits of the GC that are are already in there and occasionally collect things before they need to be collected. Until there is a new version I'm inclined to categorise anything related to more advanced operations on arrays involving no-primitive types on the "Clemow's bane" pile. First of all there is the issue that I think we are seeing here which involves the over-collection of things that aren't (yet) garbage, secondly there is the issue that if you do manage to get a item out of a array in a way like this ChucK will somehow lose track of what type it is at which point there will be issues of a extremely headache-inducing nature.
Mike may be able to help you; I seem to remember him&me got something quite similar to this to work for some of his code but I forgot the details. The one thing my memory hasn't repressed is that the solution involved sprinkling the code with magical "@" signs, more or less at random :¬). I love ChucK but here be dragons.
Yours, Kas.
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
participants (3)
-
Kassen
-
mike clemow
-
Robert Poor