vlc | branch: master | Rémi Denis-Courmont <[email protected]> | Mon Nov 29 20:15:46 2010 +0200| [a29e8329e2892ad5e0631772d3ccad24b15aaf49] | committer: Rémi Denis-Courmont
Replace vlc_detach() with simpler vlc_clone_detach() vlc_clone_detach() is less flexible but we never used that lost flexibilty. However, it will simplify a later Windows fix as well as safely exposing detached threads to plugins. > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=a29e8329e2892ad5e0631772d3ccad24b15aaf49 --- src/libvlc.h | 4 +- src/misc/pthread.c | 113 ++++++++++++++++++++++++++++----------------- src/playlist/fetcher.c | 8 +--- src/playlist/preparser.c | 8 +--- src/win32/thread.c | 14 +++++- 5 files changed, 88 insertions(+), 59 deletions(-) diff --git a/src/libvlc.h b/src/libvlc.h index dc31535..82a05d0 100644 --- a/src/libvlc.h +++ b/src/libvlc.h @@ -51,8 +51,8 @@ void system_End ( libvlc_int_t * ); * Threads subsystem */ -/* This cannot be used as is from plugins: */ -void vlc_detach (vlc_thread_t); +/* This cannot be used as is from plugins yet: */ +int vlc_clone_detach (vlc_thread_t *, void *(*)(void *), void *, int); /* Hopefully, no need to export this. There is a new thread API instead. */ void vlc_thread_cancel (vlc_object_t *); diff --git a/src/misc/pthread.c b/src/misc/pthread.c index 2da18b5..6512c2e 100644 --- a/src/misc/pthread.c +++ b/src/misc/pthread.c @@ -600,23 +600,12 @@ void vlc_threads_setup (libvlc_int_t *p_libvlc) vlc_mutex_unlock (&lock); } -/** - * Creates and starts new thread. - * - * @param p_handle [OUT] pointer to write the handle of the created thread to - * @param entry entry point for the thread - * @param data data parameter given to the entry point - * @param priority thread priority value - * @return 0 on success, a standard error code on error. - */ -int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data, - int priority) + +static int vlc_clone_attr (vlc_thread_t *th, pthread_attr_t *attr, + void *(*entry) (void *), void *data, int priority) { int ret; - pthread_attr_t attr; - pthread_attr_init (&attr); - /* Block the signals that signals interface plugin handles. * If the LibVLC caller wants to handle some signals by itself, it should * block these before whenever invoking LibVLC. And it must obviously not @@ -653,8 +642,8 @@ int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data, else sp.sched_priority += sched_get_priority_min (policy = SCHED_RR); - pthread_attr_setschedpolicy (&attr, policy); - pthread_attr_setschedparam (&attr, &sp); + pthread_attr_setschedpolicy (attr, policy); + pthread_attr_setschedparam (attr, &sp); } #else (void) priority; @@ -675,29 +664,36 @@ int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data, #define VLC_STACKSIZE (128 * sizeof (void *) * 1024) #ifdef VLC_STACKSIZE - ret = pthread_attr_setstacksize (&attr, VLC_STACKSIZE); + ret = pthread_attr_setstacksize (attr, VLC_STACKSIZE); assert (ret == 0); /* fails iif VLC_STACKSIZE is invalid */ #endif - ret = pthread_create (p_handle, &attr, entry, data); + ret = pthread_create (th, attr, entry, data); pthread_sigmask (SIG_SETMASK, &oldset, NULL); - pthread_attr_destroy (&attr); + pthread_attr_destroy (attr); return ret; } /** - * Marks a thread as cancelled. Next time the target thread reaches a - * cancellation point (while not having disabled cancellation), it will - * run its cancellation cleanup handler, the thread variable destructors, and - * terminate. vlc_join() must be used afterward regardless of a thread being - * cancelled or not. + * Creates and starts new thread. + * + * The thread must be <i>joined</i> with vlc_join() to reclaim resources + * when it is not needed anymore. + * + * @param th [OUT] pointer to write the handle of the created thread to + * (mandatory, must be non-NULL) + * @param entry entry point for the thread + * @param data data parameter given to the entry point + * @param priority thread priority value + * @return 0 on success, a standard error code on error. */ -void vlc_cancel (vlc_thread_t thread_id) +int vlc_clone (vlc_thread_t *th, void *(*entry) (void *), void *data, + int priority) { - pthread_cancel (thread_id); -#ifdef HAVE_MAEMO - pthread_kill (thread_id, SIGRTMIN); -#endif + pthread_attr_t attr; + + pthread_attr_init (&attr); + return vlc_clone_attr (th, &attr, entry, data, priority); } /** @@ -718,25 +714,56 @@ void vlc_join (vlc_thread_t handle, void **result) } /** - * Detaches a thread. When the specified thread completes, it will be - * automatically destroyed (in particular, its stack will be reclaimed), - * instead of waiting for another thread to call vlc_join(). If the thread has - * already completed, it will be destroyed immediately. + * Creates and starts new detached thread. + * A detached thread cannot be joined. Its resources will be automatically + * released whenever the thread exits (in particular, its call stack will be + * reclaimed). Nevertheless, a detached thread may + * be cancelled; this can expedite its termination. * - * When a thread performs some work asynchronously and may complete much - * earlier than it can be joined, detaching the thread can save memory. - * However, care must be taken that any resources used by a detached thread - * remains valid until the thread completes. This will typically involve some - * kind of thread-safe signaling. + * Detached thread are particularly useful when some work needs to be done + * asynchronously, that is likely to be completed much earlier than the thread + * can practically be joined. In this case, thread detach can spare memory. * - * A thread may detach itself. + * @warning Care must be taken that any resources used by the detached thread + * remains valid until the thread completes. * - * @param handle thread handle + * @note A detached thread must eventually exit just like another other + * thread. In practice, LibVLC will wait for detached threads to exit before + * it unloads the plugins. + * + * @param th [OUT] pointer to hold the thread handle, or NULL + * @param entry entry point for the thread + * @param data data parameter given to the entry point + * @param priority thread priority value + * @return 0 on success, a standard error code on error. */ -void vlc_detach (vlc_thread_t handle) +int vlc_clone_detach (vlc_thread_t *th, void *(*entry) (void *), void *data, + int priority) { - int val = pthread_detach (handle); - VLC_THREAD_ASSERT ("detaching thread"); + vlc_thread_t dummy; + pthread_attr_t attr; + + if (th == NULL) + th = &dummy; + + pthread_attr_init (&attr); + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + return vlc_clone_attr (th, &attr, entry, data, priority); +} + +/** + * Marks a thread as cancelled. Next time the target thread reaches a + * cancellation point (while not having disabled cancellation), it will + * run its cancellation cleanup handler, the thread variable destructors, and + * terminate. vlc_join() must be used afterward regardless of a thread being + * cancelled or not. + */ +void vlc_cancel (vlc_thread_t thread_id) +{ + pthread_cancel (thread_id); +#ifdef HAVE_MAEMO + pthread_kill (thread_id, SIGRTMIN); +#endif } /** diff --git a/src/playlist/fetcher.c b/src/playlist/fetcher.c index 1551020..2113d42 100644 --- a/src/playlist/fetcher.c +++ b/src/playlist/fetcher.c @@ -91,16 +91,12 @@ void playlist_fetcher_Push( playlist_fetcher_t *p_fetcher, p_fetcher->i_waiting, p_item ); if( !p_fetcher->b_live ) { - vlc_thread_t th; - - if( vlc_clone( &th, Thread, p_fetcher, VLC_THREAD_PRIORITY_LOW ) ) + if( vlc_clone_detach( NULL, Thread, p_fetcher, + VLC_THREAD_PRIORITY_LOW ) ) msg_Err( p_fetcher->p_playlist, "cannot spawn secondary preparse thread" ); else - { - vlc_detach( th ); p_fetcher->b_live = true; - } } vlc_mutex_unlock( &p_fetcher->lock ); } diff --git a/src/playlist/preparser.c b/src/playlist/preparser.c index 64182e3..dfd955a 100644 --- a/src/playlist/preparser.c +++ b/src/playlist/preparser.c @@ -83,16 +83,12 @@ void playlist_preparser_Push( playlist_preparser_t *p_preparser, input_item_t *p p_preparser->i_waiting, p_item ); if( !p_preparser->b_live ) { - vlc_thread_t th; - - if( vlc_clone( &th, Thread, p_preparser, VLC_THREAD_PRIORITY_LOW ) ) + if( vlc_clone_detach( NULL, Thread, p_preparser, + VLC_THREAD_PRIORITY_LOW ) ) msg_Warn( p_preparser->p_playlist, "cannot spawn pre-parser thread" ); else - { - vlc_detach( th ); p_preparser->b_live = true; - } } vlc_mutex_unlock( &p_preparser->lock ); } diff --git a/src/win32/thread.c b/src/win32/thread.c index 63e181d..6f745e0 100644 --- a/src/win32/thread.c +++ b/src/win32/thread.c @@ -665,15 +665,25 @@ void vlc_join (vlc_thread_t handle, void **result) #endif } -void vlc_detach (vlc_thread_t handle) +int vlc_clone_detach (vlc_thread_t *p_handle, void *(*entry) (void *), + void *data, int priority) { + vlc_thread_t th; + if (p_handle == NULL) + p_handle = &th; + + int ret = vlc_clone (p_handle, entry, data, priority); + if (ret) + return ret; + #ifndef UNDER_CE - CloseHandle (handle); + CloseHandle (*p_handle); #else /* FIXME: handle->cancel_event leak */ CloseHandle (handle->handle); free (handle); #endif + return 0; } /*** Thread cancellation ***/ _______________________________________________ vlc-commits mailing list [email protected] http://mailman.videolan.org/listinfo/vlc-commits
