[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [sc-dev] OSCFunc oneShot is breakable because of careless FunctionList implementation

Hi James and Scott,

Is the alternative of copying the array before iterating obviously worse in performance?
As in 
value { arg ... args;
var res = array.copy.collect(_.valueArray(args));
^if(flopped) { res.flop } { res }


On Dec 10, 2013, at 1:38 AM, James Harkins wrote:

On Monday, December 9, 2013 5:59:33 PM HKT, Scott Wilson wrote:
- add a 'removeLater' method. This would defer removes to a cleanup stage called at the end of the value methods. We can't modify removeFunc to do this as it needs to return the modified list. The downside of this is it only works if functions play well with modifying their lists.

Here's a patch implementing Scott's second suggestion -- to save the functions to remove, and remove them after evaluating the FunctionList is finished. It should behave identically if you removeFunc outside of FunctionList evaluation. Inside a .value call, it may leave you with a FunctionList of one function. I think that's not so terrible.

In the most basic FunctionList scenario (when none of the functions removes a function from the list), overhead should be minimal: merely assigning a Boolean variable twice. If there is a removeFunc call during evaluation, it will create an array and garbage-collect it. I think this is a relatively rare case, and even that is not much overhead. I think this answers my concern about copying and garbage-collecting arrays for a high rate of incoming OSC messages.

Unfortunately I'm having another "git moment" -- I have fetched from upstream, merged into master, but for some reason I still have the old ScIDE.sc file with the Document redirect. QGit shows me the document-related commits, but the content is not there. (Who has time for this? Seriously. Me to git: "Please use the newest content." Git to me: "No, I won't." Me to git: "Maybe I should use mercurial from now on.")

prCleanup {
if(toRemove.size > 0) {
toRemove = nil;
evaluating = false;

I tested against my original Function:play example, and it does resolve that problem.

Another test:

f = { "func f".postln };
g = { "func g".postln };

var f2 = f <> { a.removeFunc(f2) },
g2 = g <> { a.slotAt(\array).debug("array") };
a = FunctionList([f2, g2]);

func f
array: [ a Function, a Function ]  // 'array' isn't modified yet
func g
[ func f, func g ]  // 'value' result is as it should be

a.slotAt(\array);  // 'value' has finished: 1 item remains

a.value;  // only g2 runs on the next evaluation