/***** Hello Pd mailist,
I'm wondering what peoples opinions are on the subject of externals with their own threads. Are there reasons this is is not advised (e.g. reentrancy of subsequent calls)? To be specific I'm talking about threads that initiate output. I've looked at the sourcecode for netreceive and noticed the use of sys_addpollfn, but as this method is not included in m_pd.h, i wonder if it's even intended to be used in externals. One of the reasons i ask is that the example/test code attached bellow seems to work on one of my machines (Pentium 4/Fedora 2/PD 0.37.1), but when I run it on another (a PowerbookG4/Gentoo/PD 37.4) I get a stack overflow at the outlet_float.
And if i'm not supposed to use threads, any insight on the use of these sys_*poll funtions.
Regards, -S
Code sample: thread_test.pd_linux *****/
#include <m_pd.h> #include <stdlib.h> #include <pthread.h>
static t_class *thread_test_class;
typedef struct _thread_test {
t_object x_obj;
t_outlet *outlet;
pthread_t tid;
} t_thread_test;
void *thread_test_new(void){
t_thread_test *x = (t_thread_test *)pd_new(thread_test_class);
x->outlet = outlet_new(&x->x_obj, &s_float);
return x;
}
static void *aThread(void *v){
t_thread_test *x = (t_thread_test *)v;
if (pthread_detach(pthread_self()) != 0){
post("pthread_detach failed");
return (NULL);
}
post("a thread is born");
t_float aFloat = (t_float)12345;
outlet_float(x->outlet, aFloat);
return(NULL);
}
void dotest(t_thread_test *x) {
if (pthread_create(&x->tid, NULL, &aThread, (void *)x) != 0){
post("Could not create the thread");
return;
}
}
void thread_test_setup(void){
thread_test_class = class_new(gensym("thread_test"),
(t_newmethod)thread_test_new,
0,sizeof(t_thread_test),
CLASS_DEFAULT,0);
class_addmethod(thread_test_class,(t_method)dotest,
gensym("test"),0);
}
I'm wondering what peoples opinions are on the subject of externals with their own threads. Are there reasons this is is not advised (e.g. reentrancy of subsequent calls)? To be specific I'm talking about threads that initiate output. I've looked at the sourcecode for netreceive and noticed the use of sys_addpollfn, but as this method is not included in m_pd.h, i wonder if it's even intended to be used in externals. One of the reasons i ask is that the example/test code attached bellow seems to work on one of my machines (Pentium 4/Fedora 2/PD 0.37.1), but when I run it on another (a PowerbookG4/Gentoo/PD 37.4) I get a stack overflow at the outlet_float.
well ... the only clean way of synchronizing
I'm wondering what peoples opinions are on the subject of externals with their own threads. Are there reasons this is is not advised (e.g. reentrancy of subsequent calls)? To be specific I'm talking about threads that initiate output. I've looked at the sourcecode for netreceive and noticed the use of sys_addpollfn, but as this method is not included in m_pd.h, i wonder if it's even intended to be used in externals. One of the reasons i ask is that the example/test code attached bellow seems to work on one of my machines (Pentium 4/Fedora 2/PD 0.37.1), but when I run it on another (a PowerbookG4/Gentoo/PD 37.4) I get a stack overflow at the outlet_float.
well ... the only threadsafe way to synchronize helper threads with the main pd thread is to place callbacks in the scheduler. afaik the only externals using them are flext and join. still, the |read( message to the threaded soundfiler should give you an idea, how threadsafe external programming can be done. (recent devel_0_38)
problem: the possibility to place callback in the scheduler is NOT implemented in any stable release. still, i hope it will make it's way to 0.39...
cheers ... tim
I'm wondering what peoples opinions are on the subject of externals with their own threads. Are there reasons this is is not advised (e.g. reentrancy of subsequent calls)? To be specific I'm talking about threads that initiate output. I've looked at the sourcecode for netreceive and noticed the use of sys_addpollfn, but as this method is not included in m_pd.h, i wonder if it's even intended to be used in externals. One of the reasons i ask is that the example/test code attached bellow seems to work on one of my machines (Pentium 4/Fedora 2/PD 0.37.1), but when I run it on another (a PowerbookG4/Gentoo/PD 37.4) I get a stack overflow at the outlet_float.
well ... the only threadsafe way to synchronize helper threads with the main pd thread is to place callbacks in the scheduler.
Hmmm, that's not exactly true. flext has been using the sys_lock and sys_unlock calls of the PD api before the advent of sys_callback in devel_0_38. This is also threadsafe but _might_ hold the main pd thread for too long a time (although i never encountered this). The point is that in your secondary thread you are locking PD with sys_lock whenever you want to use PD API functions (like getbytes or outlet functions) and unlock it with sys_unlock when done. Clearly this time should be as short as possible. This ensures that your calls into PD happen when PD itself doesn't do that (as it is in "idle" state). Starting with devel_0_38 it would be better to use sys_callback, of course since there's no locking involved.
best greetings, Thomas