Hi all,
I am currently working on a threaded implementation of a wiimote external. The reason I was hoping threaded design would help is to avoid dropped samples when issuing commands to wiimote (e.g. rumble/led status change). So far, it seems that reading from wiimote, no matter how fast, has no impact on the audio thread. However, writing even when such action is generated through a separate thread seems to cause drop-outs in the audio thread. The external (which was not originally built by me) uses cwiid to communicate with wiimotes and my understanding is that cwiid is heavily threaded in and of itself. An example of a threaded code is below:
void *cwiid_pthread2_setRumble(void *ptr)
{
threadedFunctionParams *rPars = (threadedFunctionParams*)ptr;
t_wiimote *x = rPars->wiimote;
t_floatarg f = rPars->f;
if (x->connected)
{
if (cwiid_command(x->wiimote, CWIID_CMD_RUMBLE, f)) post("wiiremote
error: problem setting rumble."); } }
void cwiid_pthread_setRumble(t_wiimote *x, t_floatarg f)
{
threadedFunctionParams rPars;
rPars.wiimote = x;
rPars.f = f;
pthread_t thread;
int iret1;
iret1 = pthread_create( &thread, NULL, cwiid_pthread2_setRumble,
(void*) &rPars); pthread_join(thread, NULL); }
So, cwiid_pthread_setRumble is called from Pd and then it in turn creates a thread that sends info to cwiid library against which the external is linked. I am confused as to why the new thread once it has been created still affects the Pd's audio thread. Any ideas?
Best wishes,
Ico
Ivica Ico Bukvic wrote:
iret1 = pthread_create( &thread, NULL, cwiid_pthread2_setRumble, (void*) &rPars);
This creates a new thread.
pthread_join(thread, NULL);
This waits (blocking Pd's main thread) until the new thread terminates.
So, why create a new thread only to immediately wait for it to terminate
Hope this makes sense,
On Sun, 18 Oct 2009, Claude Heiland-Allen wrote:
Ivica Ico Bukvic wrote:
iret1 = pthread_create( &thread, NULL, cwiid_pthread2_setRumble, (void*) &rPars);
This creates a new thread.
pthread_join(thread, NULL);
This waits (blocking Pd's main thread) until the new thread terminates. So, why create a new thread only to immediately wait for it to terminate - that makes the program essentially behave in a single threaded way.
But if ever there's any way that this gets to run in a multithreaded way, then the post() in cwiid_pthread2_setRumble will violate the singlethreadedness of <m_pd.h> because sys_lock() is not being used.
_ _ __ ___ _____ ________ _____________ _____________________ ... | Mathieu Bouchard, Montréal, Québec. téléphone: +1.514.383.3801
hi,
here's my "template" for a threaded external. i had to use pthread, because polling an usb device was causing glitches in pd. since i didn't want to have 2 instance of pd (1 for polling usb + netsend, 1 for audio
unstable, but at least no more glitches...
if anyone can tight it up, it could be a nice template for anyone who wants to build a thread safe external!
pat
Take a look at the code in my gphoto external (in svn)
uses sys_lock() and non-joined pthreads.
.b.
Claude Heiland-Allen wrote:
Ivica Ico Bukvic wrote:
iret1 = pthread_create( &thread, NULL, cwiid_pthread2_setRumble,
(void*) &rPars);
This creates a new thread.
pthread_join(thread, NULL);
This waits (blocking Pd's main thread) until the new thread terminates.
So, why create a new thread only to immediately wait for it to terminate
- that makes the program essentially behave in a single threaded way.
Hope this makes sense,
Claude
I think a thread is likely just going to add complication here. The
HID stuff is all without threads and works well. If cwiid is already
threaded, then chances are you should be able to get data from its
threads using non-blocking calls. If it already buffers the data,
then you don't need your own thread, just get the data from cwiid's
buffer in a non-blocking way.
This is how the Linux input API works, IIRC.
.hc
On Oct 17, 2009, at 10:33 PM, Ivica Ico Bukvic wrote:
Hi all,
I am currently working on a threaded implementation of a wiimote external. The reason I was hoping threaded design would help is to
avoid dropped samples when issuing commands to wiimote (e.g. rumble/led
status change). So far, it seems that reading from wiimote, no matter how
fast, has no impact on the audio thread. However, writing even when such action is generated through a separate thread seems to cause drop-outs in the audio thread. The external (which was not originally built by
me) uses cwiid to communicate with wiimotes and my understanding is that cwiid is heavily threaded in and of itself. An example of a threaded code is below:void *cwiid_pthread2_setRumble(void *ptr) {
threadedFunctionParams *rPars = (threadedFunctionParams*)ptr; t_wiimote *x = rPars->wiimote; t_floatarg f = rPars->f;
if (x->connected) { if (cwiid_command(x->wiimote, CWIID_CMD_RUMBLE, f)) post("wiiremote error: problem setting rumble."); } }
void cwiid_pthread_setRumble(t_wiimote *x, t_floatarg f) { threadedFunctionParams rPars; rPars.wiimote = x; rPars.f = f;
pthread_t thread; int iret1;
iret1 = pthread_create( &thread, NULL, cwiid_pthread2_setRumble, (void*) &rPars); pthread_join(thread, NULL); }
So, cwiid_pthread_setRumble is called from Pd and then it in turn creates a thread that sends info to cwiid library against which the external is linked. I am confused as to why the new thread once it has been created still affects the Pd's audio thread. Any ideas?
Best wishes,
Ico
Pd-list@iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
"[W]e have invented the technology to eliminate scarcity, but we are
deliberately throwing it away to benefit those who profit from
scarcity." -John Gilmore
The problem is however that this is not the case. Whenever issuing rumble/led commands and/or toggling various features (enable ir, acc, nunchuk, etc.), cwiid call causes a dropout in audio thread. It's obvious that the initial threaded implementation done by one of my students should've been brought to closer scrutiny by myself (rather than assuming it actually works). Now, that I've been messing with it myself, I am learning a lot about pthreads and have arrived at an implementation that might seem (at least to my own limited understanding of pthreads) more feasible, except now I am getting random crashes and instabilities.
The basic premise is to wrap select functionalities in separate threads (e.g. rumble on/off) as follows:
the main struct wiimote has a variable that is set only through the main Pd thread (via incoming messages), so that whenever a rumble on message is requested, it sets this variable to 1 and when the rumble off is requested, it sets this variable to 0.
Another thread is spawned at creation time with a while loop whose variable is changed in free call (destructor) and whose thread is then exited and joined with the main thread in the free call. This thread also has usleep instruction to ensure that it does not hog CPU. Inside the while loop (apart from the usleep) it monitors the aforesaid variable in the main loop to see whether it has been changed (by comparing it to an internal variable) and if so acts upon it. Once it has acted upon it it adjusts its internal variable to match that of the external rumble variable. this way at least theoretically one would not have to deal with mutex stuff (or at least as far as I could gather), yet the thing crashes left and right. Attached is the ugly hack of a code I have so far.
Below is also code relevant to example cited above:
//this is the separate thread that is spawned at creation //x->rumble is variable from the main wiimote struct that is not changed //here but rather through external messages that call the function below //in the free() function x->rumble is set to -1 and at that point //pthread is joined before deleting the object void cwiid_pthread_setRumble(void *ptr) { threadedFunctionParams *rPars = (threadedFunctionParams*)ptr; t_wiimote *x = rPars->wiimote; t_floatarg f = rPars->f;
while(x->rumble > -1) {
if (f != x->rumble) {
f = x->rumble;
if (cwiid_command(x->wiimote, CWIID_CMD_RUMBLE, f)) {
//post("wiiremote error: problem setting rumble.");
}
} else {
usleep(10000);
}
}
pthread_exit(0);
}
//this function is called when an external message arrives requesting change in rumble status void cwiid_setRumble(t_wiimote *x, t_floatarg f) { if (x->connected) { x->rumble = f; } }
Any help in this is most appreciated.
Best wishes,
Ico
On Sun, 2009-10-18 at 17:04 -0400, Hans-Christoph Steiner wrote:
I think a thread is likely just going to add complication here. The
HID stuff is all without threads and works well. If cwiid is already
threaded, then chances are you should be able to get data from its
threads using non-blocking calls. If it already buffers the data,
then you don't need your own thread, just get the data from cwiid's
buffer in a non-blocking way.This is how the Linux input API works, IIRC.
.hc
On Oct 17, 2009, at 10:33 PM, Ivica Ico Bukvic wrote:
Hi all,
I am currently working on a threaded implementation of a wiimote external. The reason I was hoping threaded design would help is to
avoid dropped samples when issuing commands to wiimote (e.g. rumble/led
status change). So far, it seems that reading from wiimote, no matter how
fast, has no impact on the audio thread. However, writing even when such action is generated through a separate thread seems to cause drop-outs in the audio thread. The external (which was not originally built by
me) uses cwiid to communicate with wiimotes and my understanding is that cwiid is heavily threaded in and of itself. An example of a threaded code is below:void *cwiid_pthread2_setRumble(void *ptr) {
threadedFunctionParams *rPars = (threadedFunctionParams*)ptr; t_wiimote *x = rPars->wiimote; t_floatarg f = rPars->f;
if (x->connected) { if (cwiid_command(x->wiimote, CWIID_CMD_RUMBLE, f)) post("wiiremote error: problem setting rumble."); } }
void cwiid_pthread_setRumble(t_wiimote *x, t_floatarg f) { threadedFunctionParams rPars; rPars.wiimote = x; rPars.f = f;
pthread_t thread; int iret1;
iret1 = pthread_create( &thread, NULL, cwiid_pthread2_setRumble, (void*) &rPars); pthread_join(thread, NULL); }
So, cwiid_pthread_setRumble is called from Pd and then it in turn creates a thread that sends info to cwiid library against which the external is linked. I am confused as to why the new thread once it has been created still affects the Pd's audio thread. Any ideas?
Best wishes,
Ico
Pd-list@iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
"[W]e have invented the technology to eliminate scarcity, but we are
deliberately throwing it away to benefit those who profit from
scarcity." -John Gilmore
One small fix to the callback seem to have improved stability (now at least the thing loads and runs). The trick is when object is closed without explicitly disconnecting and loaded again and closed the same way (in both cases destructor ought to take care of things), the second time pd freezes. Closing object by clicking disconnect first and then closing the patch has no adverse effects.
Any ideas?
Also, as I learn more about pthreads, is the following a good/healthy approach to threaded design:
main wiimote/pd thread changes x->connection to a state that requests action from the manageConnections thread, which then in turn updates that state to something different. Since these are atomic changes and the code is to the best of my knowledge designed in such a way that only one of these can write to it at any given time (pd thread to change state but only if the manageConnections thread has finished its change of state, and manageConnections only changes its state when invoked during which time regular pd thread cannot access it).
Does this kind of design still require mutex implementation? Is this the source of instability?
Many thanks to all for your help in this matter!
Best wishes,
Ico
On Sun, 2009-10-18 at 20:22 -0400, Ivica Ico Bukvic wrote:
The problem is however that this is not the case. Whenever issuing rumble/led commands and/or toggling various features (enable ir, acc, nunchuk, etc.), cwiid call causes a dropout in audio thread. It's obvious that the initial threaded implementation done by one of my students should've been brought to closer scrutiny by myself (rather than assuming it actually works). Now, that I've been messing with it myself, I am learning a lot about pthreads and have arrived at an implementation that might seem (at least to my own limited understanding of pthreads) more feasible, except now I am getting random crashes and instabilities.
The basic premise is to wrap select functionalities in separate threads (e.g. rumble on/off) as follows:
the main struct wiimote has a variable that is set only through the main Pd thread (via incoming messages), so that whenever a rumble on message is requested, it sets this variable to 1 and when the rumble off is requested, it sets this variable to 0.
Another thread is spawned at creation time with a while loop whose variable is changed in free call (destructor) and whose thread is then exited and joined with the main thread in the free call. This thread also has usleep instruction to ensure that it does not hog CPU. Inside the while loop (apart from the usleep) it monitors the aforesaid variable in the main loop to see whether it has been changed (by comparing it to an internal variable) and if so acts upon it. Once it has acted upon it it adjusts its internal variable to match that of the external rumble variable. this way at least theoretically one would not have to deal with mutex stuff (or at least as far as I could gather), yet the thing crashes left and right. Attached is the ugly hack of a code I have so far.
Below is also code relevant to example cited above:
//this is the separate thread that is spawned at creation //x->rumble is variable from the main wiimote struct that is not changed //here but rather through external messages that call the function below //in the free() function x->rumble is set to -1 and at that point //pthread is joined before deleting the object void cwiid_pthread_setRumble(void *ptr) { threadedFunctionParams *rPars = (threadedFunctionParams*)ptr; t_wiimote *x = rPars->wiimote; t_floatarg f = rPars->f;
while(x->rumble > -1) { if (f != x->rumble) { f = x->rumble; if (cwiid_command(x->wiimote, CWIID_CMD_RUMBLE, f)) { //post("wiiremote error: problem setting rumble."); } } else { usleep(10000); } } pthread_exit(0); }
//this function is called when an external message arrives requesting change in rumble status void cwiid_setRumble(t_wiimote *x, t_floatarg f) { if (x->connected) { x->rumble = f; } }
Any help in this is most appreciated.
Best wishes,
Ico
On Sun, 2009-10-18 at 17:04 -0400, Hans-Christoph Steiner wrote:
I think a thread is likely just going to add complication here. The
HID stuff is all without threads and works well. If cwiid is already
threaded, then chances are you should be able to get data from its
threads using non-blocking calls. If it already buffers the data,
then you don't need your own thread, just get the data from cwiid's
buffer in a non-blocking way.This is how the Linux input API works, IIRC.
.hc
On Oct 17, 2009, at 10:33 PM, Ivica Ico Bukvic wrote:
Hi all,
I am currently working on a threaded implementation of a wiimote external. The reason I was hoping threaded design would help is to
avoid dropped samples when issuing commands to wiimote (e.g. rumble/led
status change). So far, it seems that reading from wiimote, no matter how
fast, has no impact on the audio thread. However, writing even when such action is generated through a separate thread seems to cause drop-outs in the audio thread. The external (which was not originally built by
me) uses cwiid to communicate with wiimotes and my understanding is that cwiid is heavily threaded in and of itself. An example of a threaded code is below:void *cwiid_pthread2_setRumble(void *ptr) {
threadedFunctionParams *rPars = (threadedFunctionParams*)ptr; t_wiimote *x = rPars->wiimote; t_floatarg f = rPars->f;
if (x->connected) { if (cwiid_command(x->wiimote, CWIID_CMD_RUMBLE, f)) post("wiiremote error: problem setting rumble."); } }
void cwiid_pthread_setRumble(t_wiimote *x, t_floatarg f) { threadedFunctionParams rPars; rPars.wiimote = x; rPars.f = f;
pthread_t thread; int iret1;
iret1 = pthread_create( &thread, NULL, cwiid_pthread2_setRumble, (void*) &rPars); pthread_join(thread, NULL); }
So, cwiid_pthread_setRumble is called from Pd and then it in turn creates a thread that sends info to cwiid library against which the external is linked. I am confused as to why the new thread once it has been created still affects the Pd's audio thread. Any ideas?
Best wishes,
Ico
Pd-list@iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
"[W]e have invented the technology to eliminate scarcity, but we are
deliberately throwing it away to benefit those who profit from
scarcity." -John Gilmore