Commit f1b595f7 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Support for cancelling self and use normal thread variable

__thread is non-standard (and would need mingw 4.3).
parent 9fda9767
...@@ -186,6 +186,7 @@ enum { ...@@ -186,6 +186,7 @@ enum {
VLC_SAVE_CANCEL, VLC_SAVE_CANCEL,
VLC_RESTORE_CANCEL, VLC_RESTORE_CANCEL,
VLC_TEST_CANCEL, VLC_TEST_CANCEL,
VLC_DO_CANCEL,
}; };
#endif #endif
......
...@@ -144,6 +144,8 @@ void vlc_pthread_fatal (const char *action, int error, ...@@ -144,6 +144,8 @@ void vlc_pthread_fatal (const char *action, int error,
(void)action; (void)error; (void)file; (void)line; (void)action; (void)error; (void)file; (void)line;
abort(); abort();
} }
static vlc_threadvar_t cancel_key;
#endif #endif
/***************************************************************************** /*****************************************************************************
...@@ -178,6 +180,9 @@ int vlc_threads_init( void ) ...@@ -178,6 +180,9 @@ int vlc_threads_init( void )
vlc_threadvar_create( &thread_object_key, NULL ); vlc_threadvar_create( &thread_object_key, NULL );
#endif #endif
vlc_threadvar_create( &msg_context_global_key, msg_StackDestroy ); vlc_threadvar_create( &msg_context_global_key, msg_StackDestroy );
#ifndef LIBVLC_USE_PTHREAD
vlc_threadvar_create( &cancel_key, free );
#endif
} }
i_initializations++; i_initializations++;
...@@ -207,6 +212,9 @@ void vlc_threads_end( void ) ...@@ -207,6 +212,9 @@ void vlc_threads_end( void )
if( i_initializations == 1 ) if( i_initializations == 1 )
{ {
vlc_object_release( p_root ); vlc_object_release( p_root );
#ifndef LIBVLC_USE_PTHREAD
vlc_threadvar_delete( &cancel_key );
#endif
vlc_threadvar_delete( &msg_context_global_key ); vlc_threadvar_delete( &msg_context_global_key );
#ifndef NDEBUG #ifndef NDEBUG
vlc_threadvar_delete( &thread_object_key ); vlc_threadvar_delete( &thread_object_key );
...@@ -838,42 +846,76 @@ void vlc_thread_cancel (vlc_object_t *obj) ...@@ -838,42 +846,76 @@ void vlc_thread_cancel (vlc_object_t *obj)
vlc_cancel (priv->thread_id); vlc_cancel (priv->thread_id);
} }
typedef struct vlc_cleanup_t
{
struct vlc_cleanup_t *next;
void (*proc) (void *);
void *data;
} vlc_cleanup_t;
typedef struct vlc_cancel_t
{
vlc_cleanup_t *cleaners;
bool killable;
bool killed;
} vlc_cancel_t;
void vlc_control_cancel (int cmd, ...) void vlc_control_cancel (int cmd, ...)
{ {
#ifdef LIBVLC_USE_PTHREAD #ifdef LIBVLC_USE_PTHREAD
(void) cmd; (void) cmd;
abort(); abort();
#else #else
static __thread struct vlc_cancel_t *stack = NULL;
static __thread bool killed = false, killable = true;
va_list ap; va_list ap;
va_start (ap, cmd); va_start (ap, cmd);
vlc_cancel_t *nfo = vlc_threadvar_get (&cancel_key);
if (nfo == NULL)
{
nfo = malloc (sizeof (*nfo));
if (nfo == NULL)
abort ();
nfo->cleaners = NULL;
nfo->killed = false;
nfo->killable = true;
}
switch (cmd) switch (cmd)
{ {
case VLC_SAVE_CANCEL: case VLC_SAVE_CANCEL:
{ {
int *p_state = va_arg (ap, int *); int *p_state = va_arg (ap, int *);
*p_state = killable; *p_state = nfo->killable;
killable = false; nfo->killable = false;
break; break;
} }
case VLC_RESTORE_CANCEL: case VLC_RESTORE_CANCEL:
{ {
int state = va_arg (ap, int); int state = va_arg (ap, int);
killable = state != 0; nfo->killable = state != 0;
break; break;
} }
case VLC_TEST_CANCEL: case VLC_TEST_CANCEL:
if (killable) if (nfo->killable && nfo->killed)
#ifdef WIN32 {
for (vlc_cleanup_t *p = nfo->cleaners; p != NULL; p = p->next)
p->proc (p->data);
free (nfo);
#if defined (LIBVLC_USE_PTHREAD)
pthread_exit (PTHREAD_CANCELLED);
#elif defined (WIN32)
_endthread (); _endthread ();
#else #else
# error Not implemented! # error Not implemented!
#endif #endif
}
break;
case VLC_DO_CANCEL:
nfo->killed = true;
break; break;
} }
va_end (ap); va_end (ap);
......
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