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

Support for cancellation cleanup functions

parent 8458705f
...@@ -187,6 +187,8 @@ enum { ...@@ -187,6 +187,8 @@ enum {
VLC_RESTORE_CANCEL, VLC_RESTORE_CANCEL,
VLC_TEST_CANCEL, VLC_TEST_CANCEL,
VLC_DO_CANCEL, VLC_DO_CANCEL,
VLC_CLEANUP_PUSH,
VLC_CLEANUP_POP,
}; };
#endif #endif
...@@ -317,6 +319,60 @@ static inline void vlc_testcancel (void) ...@@ -317,6 +319,60 @@ static inline void vlc_testcancel (void)
#endif #endif
} }
#if defined (LIBVLC_USE_PTHREAD)
/**
* Registers a new procedure to run if the thread is cancelled (or otherwise
* exits prematurely). Any call to vlc_cleanup_push() <b>must</b> paired with a
* call to either vlc_cleanup_pop() or vlc_cleanup_run(). Branching into or out
* of the block between these two function calls is not allowed (read: it will
* likely crash the whole process). If multiple procedures are registered,
* they are handled in last-in first-out order.
*
* @param routine procedure to call if the thread ends
* @param arg argument for the procedure
*/
# define vlc_cleanup_push( routine, arg ) pthread_cleanup_push (routine, arg)
/**
* Removes a cleanup procedure that was previously registered with
* vlc_cleanup_push().
*/
# define vlc_cleanup_pop( ) pthread_cleanup_pop (0)
/**
* Removes a cleanup procedure that was previously registered with
* vlc_cleanup_push(), and executes it.
*/
# define vlc_cleanup_run( ) pthread_cleanup_pop (1)
#else
typedef struct vlc_cleanup_t vlc_cleanup_t;
struct vlc_cleanup_t
{
vlc_cleanup_t *next;
void (*proc) (void *);
void *data;
};
/* This macros opens a code block on purpose. This is needed for multiple
* calls within a single function. This also prevent Win32 developpers from
* writing code that would break on POSIX (POSIX opens a block as well). */
# define vlc_cleanup_push( routine, arg ) \
do { \
vlc_cleanup_t vlc_cleanup_data = { NULL, routine, arg, }; \
vlc_control_cancel (VLC_CLEANUP_PUSH, &vlc_cleanup_data)
# define vlc_cleanup_pop( ) \
vlc_control_cancel (VLC_CLEANUP_POP); \
} while (0)
# define vlc_cleanup_run( ) \
vlc_control_cancel (VLC_CLEANUP_POP); \
vlc_cleanup_data.proc (vlc_cleanup_data.data); \
} while (0)
#endif /* LIBVLC_USE_PTHREAD */
/***************************************************************************** /*****************************************************************************
* vlc_cond_init: initialize a condition * vlc_cond_init: initialize a condition
*****************************************************************************/ *****************************************************************************/
......
...@@ -864,22 +864,19 @@ void vlc_thread_cancel (vlc_object_t *obj) ...@@ -864,22 +864,19 @@ void vlc_thread_cancel (vlc_object_t *obj)
vlc_cancel (priv->thread_id); vlc_cancel (priv->thread_id);
} }
typedef struct vlc_cleanup_t #ifndef LIBVLC_USE_PTHREAD
{
struct vlc_cleanup_t *next;
void (*proc) (void *);
void *data;
} vlc_cleanup_t;
typedef struct vlc_cancel_t typedef struct vlc_cancel_t
{ {
vlc_cleanup_t *cleaners; vlc_cleanup_t *cleaners;
bool killable; bool killable;
bool killed; bool killed;
} vlc_cancel_t; } vlc_cancel_t;
#endif
void vlc_control_cancel (int cmd, ...) void vlc_control_cancel (int cmd, ...)
{ {
/* NOTE: This function only modifies thread-specific data, so there is no
* need to lock anything. */
#ifdef LIBVLC_USE_PTHREAD #ifdef LIBVLC_USE_PTHREAD
(void) cmd; (void) cmd;
assert (0); assert (0);
...@@ -935,6 +932,22 @@ void vlc_control_cancel (int cmd, ...) ...@@ -935,6 +932,22 @@ void vlc_control_cancel (int cmd, ...)
case VLC_DO_CANCEL: case VLC_DO_CANCEL:
nfo->killed = true; nfo->killed = true;
break; break;
case VLC_CLEANUP_PUSH:
{
/* cleaner is a pointer to the caller stack, no need to allocate
* and copy anything. As a nice side effect, this cannot fail. */
vlc_cleanup_t *cleaner = va_arg (ap, vlc_cleanup_t *);
cleaner->next = nfo->cleaners;
nfo->cleaners = cleaner;
break;
}
case VLC_CLEANUP_POP:
{
nfo->cleaners = nfo->cleaners->next;
break;
}
} }
va_end (ap); va_end (ap);
#endif #endif
......
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