From 7e02520614efa677c1d8683df69a09c9f650d105 Mon Sep 17 00:00:00 2001 From: Martin Peach Date: Mon, 18 Jan 2010 17:25:08 +0000 Subject: Make the connection thread detached and don't refer to its struct directly, check for thread creation errors. svn path=/trunk/externals/mrpeach/; revision=13037 --- net/udpsend~-help.pd | 5 ++++- net/udpsend~.c | 50 +++++++++++++++++++++++++++++++++----------------- net/udpsend~.h | 2 +- 3 files changed, 38 insertions(+), 19 deletions(-) (limited to 'net') diff --git a/net/udpsend~-help.pd b/net/udpsend~-help.pd index f8bc684..1a0ab83 100644 --- a/net/udpsend~-help.pd +++ b/net/udpsend~-help.pd @@ -66,7 +66,7 @@ per sample); #X text 70 430 dsp vector size:; #X msg -258 200 channels \$1; #X obj -412 185 hradio 15 1 0 4 empty empty empty 0 -8 0 10 -4034 -1 --1 2; +-1 0; #X obj -178 297 udpsend~ 2 512; #X text -88 296 sends 2 dsp-channels using 512-sample blocks; #X obj -397 541 udpreceive~ 8008 2 512; @@ -108,6 +108,8 @@ if nothing is receiving.; #X text -256 540 receives 2 channels on port 8008 Same blocksize as udpsend~; #X floatatom -412 216 5 0 0 0 - - -; +#X obj -288 172 tgl 15 0 empty empty toggle_connection 17 7 0 10 -4034 +-1 -1 0 1; #X connect 0 0 54 0; #X connect 1 0 62 0; #X connect 2 0 62 0; @@ -159,3 +161,4 @@ udpsend~; #X connect 73 8 74 0; #X connect 73 9 8 0; #X connect 82 0 64 0; +#X connect 89 0 62 0; diff --git a/net/udpsend~.c b/net/udpsend~.c index 7e155c9..b376ffb 100644 --- a/net/udpsend~.c +++ b/net/udpsend~.c @@ -101,16 +101,17 @@ typedef struct _udpsend_tilde int x_ninlets; /* number of inlets */ int x_channels; /* number of channels we want to stream */ int x_format; /* format of streamed audio data */ -// int x_bitrate; /* specifies bitrate for compressed formats */ int x_count; /* total number of audio frames */ t_int **x_myvec; /* vector we pass on in the DSP routine */ pthread_mutex_t x_mutex; - pthread_cond_t x_requestcondition; - pthread_cond_t x_answercondition; - pthread_t x_childthread; + pthread_t x_childthread; /* a thread to initiate a connection to the remote port */ + pthread_attr_t x_childthread_attr; /* child thread should have detached attribute so it can be cleaned up after it exits. */ + int x_childthread_result; /* result from pthread_create. Zero if x_childthread represents a valid thread. */ } t_udpsend_tilde; +#define NO_CHILDTHREAD 1 /* not zero */ + /* function prototypes */ static int udpsend_tilde_sockerror(char *s); static void udpsend_tilde_closesocket(int fd); @@ -132,8 +133,8 @@ void udpsend_tilde_setup(void); static void udpsend_tilde_notify(t_udpsend_tilde *x) { pthread_mutex_lock(&x->x_mutex); - x->x_childthread = NULL; - outlet_float(x->x_outlet, x->x_connectstate); + x->x_childthread_result = NO_CHILDTHREAD; /* connection thread has ended */ + outlet_float(x->x_outlet, x->x_connectstate); /* we should be connected */ pthread_mutex_unlock(&x->x_mutex); } @@ -150,6 +151,7 @@ static void udpsend_tilde_disconnect(t_udpsend_tilde *x) pthread_mutex_unlock(&x->x_mutex); } +/* udpsend_tilde_doconnect runs in the child thread, which terminates as soon as a connection is */ static void *udpsend_tilde_doconnect(void *zz) { t_udpsend_tilde *x = (t_udpsend_tilde *)zz; @@ -171,7 +173,7 @@ static void *udpsend_tilde_doconnect(void *zz) { post("udpsend~: connection to %s on port %d failed", hostname->s_name,portno); udpsend_tilde_sockerror("socket"); - x->x_childthread = NULL; + x->x_childthread_result = NO_CHILDTHREAD; return (0); } @@ -181,7 +183,7 @@ static void *udpsend_tilde_doconnect(void *zz) if (hp == 0) { post("udpsend~: bad host?"); - x->x_childthread = NULL; + x->x_childthread_result = NO_CHILDTHREAD; return (0); } @@ -204,7 +206,7 @@ static void *udpsend_tilde_doconnect(void *zz) { udpsend_tilde_sockerror("connecting stream socket"); udpsend_tilde_closesocket(sockfd); - x->x_childthread = NULL; + x->x_childthread_result = NO_CHILDTHREAD; return (0); } @@ -213,7 +215,7 @@ static void *udpsend_tilde_doconnect(void *zz) pthread_mutex_lock(&x->x_mutex); x->x_fd = sockfd; x->x_connectstate = 1; - clock_delay(x->x_clock, 0); + clock_delay(x->x_clock, 0);/* udpsend_tilde_notify is called in next clock tick */ pthread_mutex_unlock(&x->x_mutex); return (0); } @@ -221,7 +223,7 @@ static void *udpsend_tilde_doconnect(void *zz) static void udpsend_tilde_connect(t_udpsend_tilde *x, t_symbol *host, t_floatarg fportno) { pthread_mutex_lock(&x->x_mutex); - if (x->x_childthread != NULL) + if (x->x_childthread_result == 0) { pthread_mutex_unlock(&x->x_mutex); post("udpsend~: already trying to connect"); @@ -246,7 +248,25 @@ static void udpsend_tilde_connect(t_udpsend_tilde *x, t_symbol *host, t_floatarg x->x_count = 0; /* start child thread to connect */ - pthread_create(&x->x_childthread, 0, udpsend_tilde_doconnect, x); + /* sender thread should start out detached so its resouces will be freed when it is done */ + if (0!= (x->x_childthread_result = pthread_attr_init(&x->x_childthread_attr))) + { + pthread_mutex_unlock(&x->x_mutex); + post("udpsend~: pthread_attr_init failed: %d", x->x_childthread_result); + return; + } + if(0!= (x->x_childthread_result = pthread_attr_setdetachstate(&x->x_childthread_attr, PTHREAD_CREATE_DETACHED))) + { + pthread_mutex_unlock(&x->x_mutex); + post("udpsend~: pthread_attr_setdetachstate failed: %d", x->x_childthread_result); + return; + } + if (0 != (x->x_childthread_result = pthread_create(&x->x_childthread, &x->x_childthread_attr, udpsend_tilde_doconnect, x))) + { + pthread_mutex_unlock(&x->x_mutex); + post("udpsend~: couldn't create sender thread (%d)", x->x_childthread_result); + return; + } pthread_mutex_unlock(&x->x_mutex); } @@ -553,13 +573,11 @@ static void *udpsend_tilde_new(t_floatarg inlets, t_floatarg blocksize) } pthread_mutex_init(&x->x_mutex, 0); - pthread_cond_init(&x->x_requestcondition, 0); - pthread_cond_init(&x->x_answercondition, 0); x->x_hostname = ps_localhost; x->x_portno = DEFAULT_PORT; x->x_connectstate = 0; - x->x_childthread = NULL; + x->x_childthread_result = NO_CHILDTHREAD; x->x_fd = -1; x->x_tag.format = x->x_format = SF_FLOAT; @@ -597,8 +615,6 @@ static void udpsend_tilde_free(t_udpsend_tilde* x) clock_free(x->x_clock); - pthread_cond_destroy(&x->x_requestcondition); - pthread_cond_destroy(&x->x_answercondition); pthread_mutex_destroy(&x->x_mutex); } diff --git a/net/udpsend~.h b/net/udpsend~.h index af1e07e..437cff7 100644 --- a/net/udpsend~.h +++ b/net/udpsend~.h @@ -34,7 +34,7 @@ /* Some enhancements have been made with the goal of keeping compatibility */ /* between the stream formats of streamout~/in~ and netsend~/receive~. */ -#define VERSION "0.2" +#define VERSION "0.3" #define DEFAULT_AUDIO_CHANNELS 32 /* nax. number of audio channels we support */ #define DEFAULT_AUDIO_BUFFER_SIZE 2048 /*1024*/ /* number of samples in one audio block */ -- cgit v1.2.1