Commit a29e8329 authored by Rémi Denis-Courmont's avatar 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.
parent a75bbdb2
......@@ -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 *);
......
......@@ -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.
*/
int vlc_clone_detach (vlc_thread_t *th, void *(*entry) (void *), void *data,
int priority)
{
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_detach (vlc_thread_t handle)
void vlc_cancel (vlc_thread_t thread_id)
{
int val = pthread_detach (handle);
VLC_THREAD_ASSERT ("detaching thread");
pthread_cancel (thread_id);
#ifdef HAVE_MAEMO
pthread_kill (thread_id, SIGRTMIN);
#endif
}
/**
......
......@@ -91,17 +91,13 @@ 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 );
}
......
......@@ -83,17 +83,13 @@ 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 );
}
......
......@@ -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 ***/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment