osc listener shred woes
Hello all,
So, the following code sporks out two shreds to listen for two (for
now--I want to be using 14) OSC messages, put their int values into an
event and report back to the parent shred with the value and the
address. This is supposed to be a way to get around the fact that,
a) I seem to have to listen on a different port if the OSC messages
have the same type,
b) that I can't wait on multiple events and,
c) that I want all the values to control parameters in a single patch.
My OSC messages are being lobbed at Chuck via a Python script and
everything seems to be working fine on that end. I've even gotten
this to work using two chuck shreds that were manually sporked. At
any rate, this code runs fine for about two seconds and then dies in
either a segmentation fault or a bus error.
Any guesses?
---
// extend the Event class
class Bang extends Event {
string message;
int value;
}
// a generic osc listener shred
fun void oscListener( Bang b, int port, string osctype ) {
// create our OSC receiver
OscRecv recv;
port => recv.port;
recv.listen();
// create an address in the receiver, store in new variable
recv.event( osctype ) @=> OscEvent oe;
while( true ) {
// wait for osc event to arrive
oe => now;
while( oe.nextMsg() ) {
oe.getInt() => b.value;
osctype => b.message;
b.broadcast();
}
}
}
// our event "Bang"
Bang bang;
8000 => int oscport;
// the types for the osc objects
"/leftraw, i" => string leftraw;
"/leftavg, i" => string leftavg;
spork ~ oscListener( bang, oscport, leftraw );
// shreds are usually happier listening on a separate port
spork ~ oscListener( bang, oscport + 1, leftavg );
SinOsc raw => dac;
SinOsc avg => dac;
while( true ) {
bang => now;
//<<
Whoops, I neglected to mention that this code will work if you comment
out one of the listener spork lines and only listen for one OSC event
with only one generic listener.
-mike
On Mon, Apr 28, 2008 at 2:47 AM, mike clemow
Hello all,
So, the following code sporks out two shreds to listen for two (for now--I want to be using 14) OSC messages, put their int values into an event and report back to the parent shred with the value and the address. This is supposed to be a way to get around the fact that,
a) I seem to have to listen on a different port if the OSC messages have the same type, b) that I can't wait on multiple events and, c) that I want all the values to control parameters in a single patch.
My OSC messages are being lobbed at Chuck via a Python script and everything seems to be working fine on that end. I've even gotten this to work using two chuck shreds that were manually sporked. At any rate, this code runs fine for about two seconds and then dies in either a segmentation fault or a bus error.
Any guesses?
--- // extend the Event class class Bang extends Event { string message; int value; }
// a generic osc listener shred fun void oscListener( Bang b, int port, string osctype ) { // create our OSC receiver OscRecv recv; port => recv.port; recv.listen();
// create an address in the receiver, store in new variable recv.event( osctype ) @=> OscEvent oe;
while( true ) { // wait for osc event to arrive oe => now;
while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); } } }
// our event "Bang" Bang bang; 8000 => int oscport;
// the types for the osc objects "/leftraw, i" => string leftraw; "/leftavg, i" => string leftavg;
spork ~ oscListener( bang, oscport, leftraw ); // shreds are usually happier listening on a separate port spork ~ oscListener( bang, oscport + 1, leftavg );
SinOsc raw => dac; SinOsc avg => dac;
while( true ) { bang => now; //<<
>>; if( bang.message == leftraw ) { bang.value => raw.freq; } else if( bang.message == leftavg ) { bang.value => avg.freq; } }
mike clemow wrote:
b.broadcast();
I think you should try adding: 1::samp => now; here (right after broadcast'ing). Not sure why, but it seems that handling more events in the same time-slice is problematic (or I did a mistake similar to yours). My problem wasn't seg faults, but missed events, so I might be wrong, but it might be worth a try... -- peace, love & harmony Atte http://atte.dk | http://myspace.com/attejensen http://anagrammer.dk | http://modlys.dk
My thoughts exactly! So, I was able to get better performance (e.g.
performance at all) after turning AirPort off. Then, just as you
said, my problem was missed events. My first thought was that it was
the subclassed event, so I put a random delay between 1 and 10 ms
right before b.broadcast(). That didn't help much. Then I remembered
the bus error...
Putting the same random delay just after
oe => now;
Made a huge difference. I'm not sure that it has to be a random
delay, though. I'll do some experimenting. Apparently, the various
shreds step on each other trying to access the OSC messages somehow.
I'm not sure how it works under the hood.
Thanks, Atte!
Cheers,
Mike
On Mon, Apr 28, 2008 at 3:03 AM, Atte André Jensen
mike clemow wrote:
b.broadcast();
I think you should try adding: 1::samp => now; here (right after broadcast'ing). Not sure why, but it seems that handling more events in the same time-slice is problematic (or I did a mistake similar to yours). My problem wasn't seg faults, but missed events, so I might be wrong, but it might be worth a try...
-- peace, love & harmony Atte
http://atte.dk | http://myspace.com/attejensen http://anagrammer.dk | http://modlys.dk _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
2008/4/28 Atte André Jensen
I think you should try adding: 1::samp => now; here (right after broadcast'ing). Not sure why, but it seems that handling more events in the same time-slice is problematic (or I did a mistake similar to yours). My problem wasn't seg faults, but missed events, so I might be wrong, but it might be worth a try...
The "why" is quite straightforward. Take this example; ------------------- fun void my_shred() { <<<"here I am!">>>; } spork ~my_shred(); //code ends here. --------------- This will never print the line. Why not? Well, once our code starts running it will keep doing so until it either advances time which gives other shreds a chance to run or it reaches the end. While it is running no other shreds do anything. Here the mother shred reaches her end and so exits and takes the child with her so the child never runs. The solution is "me.yield()" which gives other shreds (and their events and whatever) a chance to run yet doesn't advance time for the mother. Typically it's wise to use that command right after signalling or broadcasting a event or sporking a shred. Generally speaking; ChucK manages a lot of the issues with concurrency for us but it still needs some care and attention because it's still a somewhat hard subject, even when it's made this friendly. I think that's good; ChucK's timing is completely deterministic and does exactly what we tell it but from time to time that means being quite explicid if we want it to behave. I hope that clarifies things a bit. Yours, Kas.
Kassen wrote:
The solution is "me.yield()" which gives other shreds (and their events and whatever) a chance to run yet doesn't advance time for the mother.
Ok, so to put in a language that I understand, are you saying I should replace my 1::samp => now with me.yield()? -- peace, love & harmony Atte http://atte.dk | http://myspace.com/attejensen http://anagrammer.dk | http://modlys.dk
2008/4/28 Atte André Jensen
Ok, so to put in a language that I understand, are you saying I should replace my 1::samp => now with me.yield()?
Yes, I think so. Advancing time, which is what you are doing, gives other shreds a chance to run but it also means this shred will only get the cpu back in a while. The difference is likely academic but if OSC messages would be flooding in faster then you are advancing time the cue would pile up and latency (or worse) would follow. The core concept here is that "samp => now" does two things; a) hand the cpu to other shreds b) make the next bit of code execute in a while (likely a 44K'th of a second here) me.yield() only does the first of the two and not the second. The issue is that while it may look like ChucK is aimed towards parallel-processing it's in fact very much focussed on making multiple processes take turns sequentially. What we are dealing with here is (amongst other issues) this exact sequence. Hope that helps, Kas.
there is a known bug with OSC receiving on multiple ports, which may account for this. it's been reported: http://wiki.cs.princeton.edu/index.php/OSC_multiple_port_bug dt On Apr 28, 2008, at 2:47 AM, mike clemow wrote:
Hello all,
So, the following code sporks out two shreds to listen for two (for now--I want to be using 14) OSC messages, put their int values into an event and report back to the parent shred with the value and the address. This is supposed to be a way to get around the fact that,
a) I seem to have to listen on a different port if the OSC messages have the same type, b) that I can't wait on multiple events and, c) that I want all the values to control parameters in a single patch.
My OSC messages are being lobbed at Chuck via a Python script and everything seems to be working fine on that end. I've even gotten this to work using two chuck shreds that were manually sporked. At any rate, this code runs fine for about two seconds and then dies in either a segmentation fault or a bus error.
Any guesses?
--- // extend the Event class class Bang extends Event { string message; int value; }
// a generic osc listener shred fun void oscListener( Bang b, int port, string osctype ) { // create our OSC receiver OscRecv recv; port => recv.port; recv.listen();
// create an address in the receiver, store in new variable recv.event( osctype ) @=> OscEvent oe;
while( true ) { // wait for osc event to arrive oe => now;
while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); } } }
// our event "Bang" Bang bang; 8000 => int oscport;
// the types for the osc objects "/leftraw, i" => string leftraw; "/leftavg, i" => string leftavg;
spork ~ oscListener( bang, oscport, leftraw ); // shreds are usually happier listening on a separate port spork ~ oscListener( bang, oscport + 1, leftavg );
SinOsc raw => dac; SinOsc avg => dac;
while( true ) { bang => now; //<<
>>; if( bang.message == leftraw ) { bang.value => raw.freq; } else if( bang.message == leftavg ) { bang.value => avg.freq; } } _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
I don't know about the segv signal, but it seems to me that there is only
one Bang instance that is shared by all iterations/shreds. This means that
if two events arrive at this loop:
while( oe.nextMsg() ) {
oe.getInt() => b.value;
osctype => b.message;
b.broadcast();
}
the second's values will overwrite those of the first (value and message
from the first event will be lost). Also, if the two oscListener shreds
happen to call broadcast simultaneously, one shred's bang values will
overwrite the other's.
I'm wondering about this statement:
osctype => b.message;
Will it cause some kind of copied string object? Probably not, I guess. The
lack of garbage collection of strings has been one of my woes when composing
OSC addresses.
/Stefan
On Mon, Apr 28, 2008 at 1:24 PM, dan trueman
there is a known bug with OSC receiving on multiple ports, which may account for this. it's been reported: http://wiki.cs.princeton.edu/index.php/OSC_multiple_port_bug
dt
On Apr 28, 2008, at 2:47 AM, mike clemow wrote:
Hello all,
So, the following code sporks out two shreds to listen for two (for now--I want to be using 14) OSC messages, put their int values into an event and report back to the parent shred with the value and the address. This is supposed to be a way to get around the fact that,
a) I seem to have to listen on a different port if the OSC messages have the same type, b) that I can't wait on multiple events and, c) that I want all the values to control parameters in a single patch.
My OSC messages are being lobbed at Chuck via a Python script and everything seems to be working fine on that end. I've even gotten this to work using two chuck shreds that were manually sporked. At any rate, this code runs fine for about two seconds and then dies in either a segmentation fault or a bus error.
Any guesses?
--- // extend the Event class class Bang extends Event { string message; int value; }
// a generic osc listener shred fun void oscListener( Bang b, int port, string osctype ) { // create our OSC receiver OscRecv recv; port => recv.port; recv.listen();
// create an address in the receiver, store in new variable recv.event( osctype ) @=> OscEvent oe;
while( true ) { // wait for osc event to arrive oe => now;
while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); } } }
// our event "Bang" Bang bang; 8000 => int oscport;
// the types for the osc objects "/leftraw, i" => string leftraw; "/leftavg, i" => string leftavg;
spork ~ oscListener( bang, oscport, leftraw ); // shreds are usually happier listening on a separate port spork ~ oscListener( bang, oscport + 1, leftavg );
SinOsc raw => dac; SinOsc avg => dac;
while( true ) { bang => now; //<<
>>; if( bang.message == leftraw ) { bang.value => raw.freq; } else if( bang.message == leftavg ) { bang.value => avg.freq; } } _______________________________________________ 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
-- Release me, insect, or I will destroy the Cosmos!
2008/4/28 Stefan Blixt
I don't know about the segv signal, but it seems to me that there is only one Bang instance that is shared by all iterations/shreds. This means that if two events arrive at this loop:
while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); }
the second's values will overwrite those of the first (value and message from the first event will be lost).
I think that's right and I think the way around this would be while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); //yield to receiving shreds, //then continue processing the message cue me.yield(); } This is the exact same principle I talked about earlier in this topic; if you don't yield you don't give the waiting shreds a chance to run. Advancing time here would probably not be a good idea. Yours, Kas.
Yeah, but note that there are two shreds running this loop in parallell. So
if one event on each port arrive at the same time, chances are that the
first yield will hand over execution to the second shred, that in turn
overwrites b.value and b.message. I think you need at least two Bang
instances to be sure that this doesn't happen.
/Stefan
On Mon, Apr 28, 2008 at 5:10 PM, Kassen
2008/4/28 Stefan Blixt
: I don't know about the segv signal, but it seems to me that there is only one Bang instance that is shared by all iterations/shreds. This means that if two events arrive at this loop:
while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); }
the second's values will overwrite those of the first (value and message from the first event will be lost).
I think that's right and I think the way around this would be
while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); //yield to receiving shreds, //then continue processing the message cue me.yield(); }
This is the exact same principle I talked about earlier in this topic; if you don't yield you don't give the waiting shreds a chance to run. Advancing time here would probably not be a good idea.
Yours, Kas.
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
-- Release me, insect, or I will destroy the Cosmos!
Actually, come to think of it, Mike, why have the Bang object at all? Why
not just move the code (the if statements) from the main loop into the
oscListener loops/shreds, and replace the broadcast with actual
functionality instead? Maybe there is some more advanced stuff that you
haven't included that prevents this?
/Stefan
On Mon, Apr 28, 2008 at 6:00 PM, Stefan Blixt
Yeah, but note that there are two shreds running this loop in parallell. So if one event on each port arrive at the same time, chances are that the first yield will hand over execution to the second shred, that in turn overwrites b.value and b.message. I think you need at least two Bang instances to be sure that this doesn't happen.
/Stefan
On Mon, Apr 28, 2008 at 5:10 PM, Kassen
wrote: 2008/4/28 Stefan Blixt
: I don't know about the segv signal, but it seems to me that there is only one Bang instance that is shared by all iterations/shreds. This means that if two events arrive at this loop:
while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); }
the second's values will overwrite those of the first (value and message from the first event will be lost).
I think that's right and I think the way around this would be
while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); //yield to receiving shreds, //then continue processing the message cue me.yield(); }
This is the exact same principle I talked about earlier in this topic; if you don't yield you don't give the waiting shreds a chance to run. Advancing time here would probably not be a good idea.
Yours, Kas.
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
-- Release me, insect, or I will destroy the Cosmos!
-- Release me, insect, or I will destroy the Cosmos!
Wow, okay... Trying to make sense of this...
Actually, come to think of it, Mike, why have the Bang object at all? Why not just move the code (the if statements) from the main loop into the oscListener loops/shreds, and replace the broadcast with actual functionality instead? Maybe there is some more advanced stuff that you haven't included that prevents this?
No, the only thing that I left out were the spork lines for the other
12 OSC listeners I need. :)
I guess the answer to your question is that I never thought of doing
that because I'm still trying to wrap my head around Chuck's notions
of scope. What you're indirectly telling me is that it's possible to
access my SinOsc objects (and indeed my whole patch) from the other
shreds, which I imagined would not be possible because of scope
limitations. However, considering how classes work, I'm clearly not
fully grasping reality here. I thought that the only way I could
share data between shreds was an event.
Kassen, I completely forgot about me.yield(), which makes me feel
pretty dumb. But I guess concurrency is not as simple as Chuck leads
me to believe!
Dan, thanks for pointing out the bug. Honestly, I seem to remember
running into issues where if I had one OSC message with a signature of
"/test, i" and another with a signature of "/mike, i" and both were
coming in on the same port, that Chuck couldn't tell the difference
between them for some reason. I remember fixing this with multiple
listeners on multiple ports. Perhaps I was doing something else
wrong.
I'm going to mess around with these excellent suggestions and get back
to you all. (sadly, this is all due today. oh well.)
Thanks!
Mike
On Mon, Apr 28, 2008 at 12:10 PM, Stefan Blixt
Actually, come to think of it, Mike, why have the Bang object at all? Why not just move the code (the if statements) from the main loop into the oscListener loops/shreds, and replace the broadcast with actual functionality instead? Maybe there is some more advanced stuff that you haven't included that prevents this?
/Stefan
Yeah, but note that there are two shreds running this loop in parallell. So if one event on each port arrive at the same time, chances are that the first yield will hand over execution to the second shred, that in turn overwrites b.value and b.message. I think you need at least two Bang instances to be sure that this doesn't happen.
/Stefan
On Mon, Apr 28, 2008 at 5:10 PM, Kassen
wrote: 2008/4/28 Stefan Blixt
: I don't know about the segv signal, but it seems to me that there is
only one Bang instance that is shared by all iterations/shreds. This means
On Mon, Apr 28, 2008 at 6:00 PM, Stefan Blixt
wrote: that if two events arrive at this loop: while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); }
the second's values will overwrite those of the first (value and
message from the first event will be lost).
I think that's right and I think the way around this would be
while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); //yield to receiving shreds, //then continue processing the message cue me.yield(); }
This is the exact same principle I talked about earlier in this topic; if you don't yield you don't give the waiting shreds a chance to run. Advancing time here would probably not be a good idea.
Yours, Kas.
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
-- Release me, insect, or I will destroy the Cosmos!
-- Release me, insect, or I will destroy the Cosmos! _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Hey folks,
So, using a combination of suggestions, I have arrived at a much
simpler version of the code that seems to work great. I haven't
scaled it up to grab all 14 OSC message types, but I think that I'm in
a much better place to do so at this point. I might have too many
me.yield() calls now, actually, but it works tons better.
thanks again!
mike
---
8000 => int oscport;
// the messages for the osc objects
"/leftraw, i" => string leftraw;
"/leftavg, i" => string leftavg;
spork ~ oscListener( oscport, leftraw );
me.yield();
spork ~ oscListener( oscport, leftavg );
me.yield();
SinOsc raw => dac;
SinOsc avg => dac;
// a generic osc listener shred
fun void oscListener( int port, string osctype ) {
// create our OSC receiver
OscRecv recv;
port => recv.port;
recv.listen();
int val;
string type;
// create an address in the receiver, store in new variable
recv.event( osctype ) @=> OscEvent oe;
while( true ) {
// wait for osc event to arrive
oe => now;
while( oe.nextMsg() ) {
oe.getInt() => val;
osctype => type;
if( type == leftraw ) {
val => raw.freq;
}
else if( type == leftavg ) {
val => avg.freq;
}
me.yield();
}
}
}
while( true ) {
1::second => now;
}
On Mon, Apr 28, 2008 at 2:43 PM, mike clemow
Wow, okay... Trying to make sense of this...
Actually, come to think of it, Mike, why have the Bang object at all? Why not just move the code (the if statements) from the main loop into the oscListener loops/shreds, and replace the broadcast with actual functionality instead? Maybe there is some more advanced stuff that you haven't included that prevents this?
No, the only thing that I left out were the spork lines for the other 12 OSC listeners I need. :)
I guess the answer to your question is that I never thought of doing that because I'm still trying to wrap my head around Chuck's notions of scope. What you're indirectly telling me is that it's possible to access my SinOsc objects (and indeed my whole patch) from the other shreds, which I imagined would not be possible because of scope limitations. However, considering how classes work, I'm clearly not fully grasping reality here. I thought that the only way I could share data between shreds was an event.
Kassen, I completely forgot about me.yield(), which makes me feel pretty dumb. But I guess concurrency is not as simple as Chuck leads me to believe!
Dan, thanks for pointing out the bug. Honestly, I seem to remember running into issues where if I had one OSC message with a signature of "/test, i" and another with a signature of "/mike, i" and both were coming in on the same port, that Chuck couldn't tell the difference between them for some reason. I remember fixing this with multiple listeners on multiple ports. Perhaps I was doing something else wrong.
I'm going to mess around with these excellent suggestions and get back to you all. (sadly, this is all due today. oh well.)
Thanks! Mike
On Mon, Apr 28, 2008 at 12:10 PM, Stefan Blixt
wrote: Actually, come to think of it, Mike, why have the Bang object at all? Why not just move the code (the if statements) from the main loop into the oscListener loops/shreds, and replace the broadcast with actual functionality instead? Maybe there is some more advanced stuff that you haven't included that prevents this?
/Stefan
Yeah, but note that there are two shreds running this loop in parallell. So if one event on each port arrive at the same time, chances are that the first yield will hand over execution to the second shred, that in turn overwrites b.value and b.message. I think you need at least two Bang instances to be sure that this doesn't happen.
/Stefan
On Mon, Apr 28, 2008 at 5:10 PM, Kassen
wrote: 2008/4/28 Stefan Blixt
: I don't know about the segv signal, but it seems to me that there is
only one Bang instance that is shared by all iterations/shreds. This means
On Mon, Apr 28, 2008 at 6:00 PM, Stefan Blixt
wrote: that if two events arrive at this loop: while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); }
the second's values will overwrite those of the first (value and
message from the first event will be lost).
I think that's right and I think the way around this would be
while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); //yield to receiving shreds, //then continue processing the message cue me.yield(); }
This is the exact same principle I talked about earlier in this topic; if you don't yield you don't give the waiting shreds a chance to run. Advancing time here would probably not be a good idea.
Yours, Kas.
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
-- Release me, insect, or I will destroy the Cosmos!
-- Release me, insect, or I will destroy the Cosmos! _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
Sorry if I came across as a big arrogant earlier - it's an interesting
problem. I got to thinking while walking home from work if you couldn't use
some polymorphic class setup. Here's a thing i tried:
----------------------------------
class OscListener {
fun void listenOnOsc(string msg, int port) {
OscRecv recv;
port => recv.port;
recv.listen();
recv.event(msg) @=> OscEvent oe;
while (true) {
oe => now;
while (oe.nextMsg()) {
receiveEvent(oe);
}
}
}
fun void receiveEvent(OscEvent oe) {
}
}
SinOsc raw => dac;
SinOsc avg => dac;
//---- Listen on OSC for raw
class ListenOnRaw extends OscListener {
fun void receiveEvent(OscEvent oe) {
<<< "Received raw event" >>>;
oe.getInt() => raw.freq;
}
}
ListenOnRaw listenOnRaw;
spork ~ listenOnRaw.listenOnOsc("/leftraw/press,i", 8000);
//---- Listen on OSC for avg
class ListenOnAvg extends OscListener {
fun void receiveEvent(OscEvent oe) {
<<< "Received avg event" >>>;
oe.getInt() => avg.freq;
}
}
ListenOnAvg listenOnAvg;
spork ~ listenOnAvg.listenOnOsc("/leftavg/press,i", 8001);
while (true) {
1::second => now;
}
----------------------------------
I tried out a modified version of this code - I only have one OSC-sending
device that sends three parameters - but I think it should work. However you
do this, I agree that it amounts up to a lot of code for each kind of OSC
message, but I guess it can't be avoided.
Hope you get everything in order for the installation!
/Stefan
On Mon, Apr 28, 2008 at 8:43 PM, mike clemow
Wow, okay... Trying to make sense of this...
Actually, come to think of it, Mike, why have the Bang object at all? Why not just move the code (the if statements) from the main loop into the oscListener loops/shreds, and replace the broadcast with actual functionality instead? Maybe there is some more advanced stuff that you haven't included that prevents this?
No, the only thing that I left out were the spork lines for the other 12 OSC listeners I need. :)
I guess the answer to your question is that I never thought of doing that because I'm still trying to wrap my head around Chuck's notions of scope. What you're indirectly telling me is that it's possible to access my SinOsc objects (and indeed my whole patch) from the other shreds, which I imagined would not be possible because of scope limitations. However, considering how classes work, I'm clearly not fully grasping reality here. I thought that the only way I could share data between shreds was an event.
Kassen, I completely forgot about me.yield(), which makes me feel pretty dumb. But I guess concurrency is not as simple as Chuck leads me to believe!
Dan, thanks for pointing out the bug. Honestly, I seem to remember running into issues where if I had one OSC message with a signature of "/test, i" and another with a signature of "/mike, i" and both were coming in on the same port, that Chuck couldn't tell the difference between them for some reason. I remember fixing this with multiple listeners on multiple ports. Perhaps I was doing something else wrong.
I'm going to mess around with these excellent suggestions and get back to you all. (sadly, this is all due today. oh well.)
Thanks! Mike
Actually, come to think of it, Mike, why have the Bang object at all? Why not just move the code (the if statements) from the main loop into the oscListener loops/shreds, and replace the broadcast with actual functionality instead? Maybe there is some more advanced stuff that you haven't included that prevents this?
/Stefan
On Mon, Apr 28, 2008 at 6:00 PM, Stefan Blixt
wrote: Yeah, but note that there are two shreds running this loop in
So if one event on each port arrive at the same time, chances are that
On Mon, Apr 28, 2008 at 12:10 PM, Stefan Blixt
wrote: parallell. the first yield will hand over execution to the second shred, that in turn overwrites b.value and b.message. I think you need at least two Bang instances to be sure that this doesn't happen.
/Stefan
On Mon, Apr 28, 2008 at 5:10 PM, Kassen
wrote:
2008/4/28 Stefan Blixt
: I don't know about the segv signal, but it seems to me that there
is only one Bang instance that is shared by all iterations/shreds. This means that if two events arrive at this loop:
while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); }
the second's values will overwrite those of the first (value and
message from the first event will be lost).
I think that's right and I think the way around this would be
while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); //yield to receiving shreds, //then continue processing the message cue me.yield(); }
This is the exact same principle I talked about earlier in this topic; if you don't yield you don't give the waiting shreds a chance to run. Advancing time here would probably not be a good idea.
Yours, Kas.
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
-- Release me, insect, or I will destroy the Cosmos!
-- Release me, insect, or I will destroy the Cosmos! _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
-- http://semiotech.org _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
-- Release me, insect, or I will destroy the Cosmos!
Stefan,
Sorry if I came across as a big arrogant earlier
You didn't come across as arrogant at all! I really appreciate your
feedback. I hadn't thought about using classes to encapsulate this
process. I think it's difficult to tell with only one or two OSC
messages which method scales better, although I imagine this is what
classes (as limited as they are in Chuck) are good for (i.e. making
scaling up less hairy).
I think that the me.yield() issue may also apply to your
implementation as well--Kassen, any thoughts?
Meanwhile, I now have multiple working options where before I had
none. So, thanks again!
cheers,
mike
On Mon, Apr 28, 2008 at 4:19 PM, Stefan Blixt
Sorry if I came across as a big arrogant earlier - it's an interesting problem. I got to thinking while walking home from work if you couldn't use some polymorphic class setup. Here's a thing i tried:
----------------------------------
class OscListener {
fun void listenOnOsc(string msg, int port) {
OscRecv recv;
port => recv.port;
recv.listen();
recv.event(msg) @=> OscEvent oe;
while (true) {
oe => now;
while (oe.nextMsg()) {
receiveEvent(oe);
}
}
}
fun void receiveEvent(OscEvent oe) {
}
}
SinOsc raw => dac;
SinOsc avg => dac;
//---- Listen on OSC for raw
class ListenOnRaw extends OscListener {
fun void receiveEvent(OscEvent oe) {
<<< "Received raw event" >>>;
oe.getInt() => raw.freq;
}
}
ListenOnRaw listenOnRaw;
spork ~ listenOnRaw.listenOnOsc("/leftraw/press,i", 8000);
//---- Listen on OSC for avg
class ListenOnAvg extends OscListener {
fun void receiveEvent(OscEvent oe) {
<<< "Received avg event" >>>;
oe.getInt() => avg.freq;
}
}
ListenOnAvg listenOnAvg;
spork ~ listenOnAvg.listenOnOsc("/leftavg/press,i", 8001);
while (true) {
1::second => now;
} ---------------------------------- I tried out a modified version of this code - I only have one OSC-sending device that sends three parameters - but I think it should work. However you do this, I agree that it amounts up to a lot of code for each kind of OSC message, but I guess it can't be avoided.
Hope you get everything in order for the installation!
/Stefan
On Mon, Apr 28, 2008 at 8:43 PM, mike clemow
wrote: Wow, okay... Trying to make sense of this...
Actually, come to think of it, Mike, why have the Bang object at all? Why not just move the code (the if statements) from the main loop into the oscListener loops/shreds, and replace the broadcast with actual functionality instead? Maybe there is some more advanced stuff that you haven't included that prevents this?
No, the only thing that I left out were the spork lines for the other 12 OSC listeners I need. :)
I guess the answer to your question is that I never thought of doing that because I'm still trying to wrap my head around Chuck's notions of scope. What you're indirectly telling me is that it's possible to access my SinOsc objects (and indeed my whole patch) from the other shreds, which I imagined would not be possible because of scope limitations. However, considering how classes work, I'm clearly not fully grasping reality here. I thought that the only way I could share data between shreds was an event.
Kassen, I completely forgot about me.yield(), which makes me feel pretty dumb. But I guess concurrency is not as simple as Chuck leads me to believe!
Dan, thanks for pointing out the bug. Honestly, I seem to remember running into issues where if I had one OSC message with a signature of "/test, i" and another with a signature of "/mike, i" and both were coming in on the same port, that Chuck couldn't tell the difference between them for some reason. I remember fixing this with multiple listeners on multiple ports. Perhaps I was doing something else wrong.
I'm going to mess around with these excellent suggestions and get back to you all. (sadly, this is all due today. oh well.)
Thanks! Mike
Actually, come to think of it, Mike, why have the Bang object at all? Why not just move the code (the if statements) from the main loop into the oscListener loops/shreds, and replace the broadcast with actual functionality instead? Maybe there is some more advanced stuff that you haven't included that prevents this?
/Stefan
On Mon, Apr 28, 2008 at 6:00 PM, Stefan Blixt
wrote: Yeah, but note that there are two shreds running this loop in
So if one event on each port arrive at the same time, chances are that
On Mon, Apr 28, 2008 at 12:10 PM, Stefan Blixt
wrote: parallell. the first yield will hand over execution to the second shred, that in turn overwrites b.value and b.message. I think you need at least two Bang instances to be sure that this doesn't happen.
/Stefan
On Mon, Apr 28, 2008 at 5:10 PM, Kassen
wrote:
2008/4/28 Stefan Blixt
: I don't know about the segv signal, but it seems to me that there
is only one Bang instance that is shared by all iterations/shreds. This means that if two events arrive at this loop:
while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); }
the second's values will overwrite those of the first (value and
message from the first event will be lost).
I think that's right and I think the way around this would be
while( oe.nextMsg() ) { oe.getInt() => b.value; osctype => b.message; b.broadcast(); //yield to receiving shreds, //then continue processing the message cue me.yield(); }
This is the exact same principle I talked about earlier in this topic; if you don't yield you don't give the waiting shreds a chance to run. Advancing time here would probably not be a good idea.
Yours, Kas.
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
-- Release me, insect, or I will destroy the Cosmos!
-- Release me, insect, or I will destroy the Cosmos! _______________________________________________ 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
-- Release me, insect, or I will destroy the Cosmos! _______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
2008/4/28 mike clemow
Kassen, I completely forgot about me.yield(), which makes me feel pretty dumb. But I guess concurrency is not as simple as Chuck leads me to believe!
Don't. In fact I have a suspicion, looking at things like we are now, that I too missed it a few times in recent history. It's a specialist tool and kind of out of the way, syntactically. I think I pointed out before (on the forum, I think) that while ChucK is deterministic in timing that doesn't need to inherently mean you or me will be able to easily predict timing in tricky cases like this. Especially the event cue here is a questionable bit, at the very least the priority (order of execution) between OSC messages and ChucKian events while yielding is underdocumented as far as I can tell. I fear Ge will have to shed (shred?, seeing how he's quite bussy these days...) a light on this issue and IMHO it's clear that the OSC hyrarchy needs cleaning up as well. I realise this is a urgent question to some and in that sense a bad thing, but I also feel it's very good that this issue which is very much at the core of ChucK's way of dealing with concurency and timing is brought to light in such a clear and practical way now. Similar scenarios have been naging me for a while now but never in such a practical and clear way. Yours, Kas.
Well, I'm glad that this is a good example of the timing/concurrency
issues at the heart of Chuck's model. I certainly have learned a lot
through this. Perhaps a collection of Chuck Concurrency "Best
Practices" can come out of this. Wiki-fodder, if nothing else.
I hold OSC very close to my heart, since a lot of my audio work is now
being done on networks of machines (an environment Chuck is rather
well primed for), but the concurrency model is throwing up a bit of a
learning curve. I think that working through it, however, will reveal
a number of paradigms that will make my code all the better for it, so
thanks to everyone for helping me out.
Cheers,
Mike
On Mon, Apr 28, 2008 at 7:23 PM, Kassen
2008/4/28 mike clemow
: Kassen, I completely forgot about me.yield(), which makes me feel pretty dumb. But I guess concurrency is not as simple as Chuck leads me to believe!
Don't.
In fact I have a suspicion, looking at things like we are now, that I too missed it a few times in recent history. It's a specialist tool and kind of out of the way, syntactically.
I think I pointed out before (on the forum, I think) that while ChucK is deterministic in timing that doesn't need to inherently mean you or me will be able to easily predict timing in tricky cases like this. Especially the event cue here is a questionable bit, at the very least the priority (order of execution) between OSC messages and ChucKian events while yielding is underdocumented as far as I can tell.
I fear Ge will have to shed (shred?, seeing how he's quite bussy these days...) a light on this issue and IMHO it's clear that the OSC hyrarchy needs cleaning up as well.
I realise this is a urgent question to some and in that sense a bad thing, but I also feel it's very good that this issue which is very much at the core of ChucK's way of dealing with concurency and timing is brought to light in such a clear and practical way now. Similar scenarios have been naging me for a while now but never in such a practical and clear way.
Yours, Kas.
_______________________________________________ chuck-users mailing list chuck-users@lists.cs.princeton.edu https://lists.cs.princeton.edu/mailman/listinfo/chuck-users
2008/4/28 Stefan Blixt
Yeah, but note that there are two shreds running this loop in parallell. So if one event on each port arrive at the same time, chances are that the first yield will hand over execution to the second shred, that in turn overwrites b.value and b.message.
Ow, right, yes, oops, that would be a issue indeed because the OSC event will be higher on the "list of things to wait for" (I still think we should yield there, BTW, as that's at least one part of the issue). Erm..... that makes it quite hard indeed. I was thinking about a "has_been_parsed" flag in the event that's set to "1" at sending it and "0" when receiving it, then have the OSC shreds yield while this is true but they'd probably keep yiedling to eachother and maybe even get the VM stuck. I'm not a 100% sure there, I don't think the way that part of the concurency works is documented at all. That could really stand some documenting. Erm.... Ge? Yours, Kas.
participants (5)
-
Atte André Jensen
-
dan trueman
-
Kassen
-
mike clemow
-
Stefan Blixt