[vlc-devel] [PATCH 1/2] win32: add cancel functions to be called in the APC
Steve Lhomme
robux4 at videolabs.io
Fri Jan 15 17:16:21 CET 2016
--
this is going to be useful to cancel socket tasks that are not alertable
---
include/vlc_threads.h | 17 +++++++++++++++++
src/win32/thread.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+)
diff --git a/include/vlc_threads.h b/include/vlc_threads.h
index b31c885..164847e 100644
--- a/include/vlc_threads.h
+++ b/include/vlc_threads.h
@@ -858,11 +858,16 @@ VLC_API unsigned vlc_GetCPUCount(void);
*/
# define vlc_cleanup_pop( ) pthread_cleanup_pop (0)
+# define vlc_cancel_push( routine, arg )
+# define vlc_cancel_pop( )
+
#else
enum
{
VLC_CLEANUP_PUSH,
VLC_CLEANUP_POP,
+ VLC_CANCEL_PUSH,
+ VLC_CANCEL_POP,
};
typedef struct vlc_cleanup_t vlc_cleanup_t;
@@ -885,6 +890,18 @@ struct vlc_cleanup_t
vlc_control_cancel (VLC_CLEANUP_POP); \
} while (0)
+#define vlc_cancel_push( routine, arg ) \
+ do { \
+ vlc_cleanup_t vlc_cleaner_data = { NULL, routine, arg, }; \
+ vlc_control_cancel (VLC_CANCEL_PUSH, &vlc_cleaner_data)
+
+/* The cleanup routine is only executed if the canceler hasn't been
+ * called
+ */
+# define vlc_cancel_pop( ) \
+ vlc_control_cancel (VLC_CANCEL_POP); \
+ } while (0)
+
#endif /* !LIBVLC_USE_PTHREAD_CLEANUP */
static inline void vlc_cleanup_lock (void *lock)
diff --git a/src/win32/thread.c b/src/win32/thread.c
index 774d4db..d9d2b50 100644
--- a/src/win32/thread.c
+++ b/src/win32/thread.c
@@ -442,6 +442,7 @@ retry:
/*** Threads ***/
static DWORD thread_key;
+static DWORD cancel_key;
struct vlc_thread
{
@@ -454,6 +455,7 @@ struct vlc_thread
atomic_bool killed;
#endif
vlc_cleanup_t *cleaners;
+ vlc_cleanup_t *cancelers;
void *(*entry) (void *);
void *data;
@@ -499,6 +501,7 @@ static int vlc_clone_attr (vlc_thread_t *p_handle, bool detached,
atomic_init(&th->killed, false);
#endif
th->cleaners = NULL;
+ th->cancelers = NULL;
/* When using the MSVCRT C library you have to use the _beginthreadex
* function instead of CreateThread, otherwise you'll end up with
@@ -573,7 +576,11 @@ static void CALLBACK vlc_cancel_self (ULONG_PTR self)
struct vlc_thread *th = (void *)self;
if (likely(th != NULL))
+ {
th->killed = true;
+ for (vlc_cleanup_t *p = th->cancelers; p != NULL; p = p->next)
+ p->proc (p->data);
+ }
}
#endif
@@ -662,6 +669,22 @@ void vlc_control_cancel (int cmd, ...)
th->cleaners = th->cleaners->next;
break;
}
+
+ case VLC_CANCEL_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 *canceler = va_arg (ap, vlc_cleanup_t *);
+ canceler->next = th->cancelers;
+ th->cancelers = canceler;
+ break;
+ }
+
+ case VLC_CANCEL_POP:
+ {
+ th->cancelers = th->cancelers->next;
+ break;
+ }
}
va_end (ap);
}
@@ -1031,6 +1054,12 @@ BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
thread_key = TlsAlloc();
if (unlikely(thread_key == TLS_OUT_OF_INDEXES))
return FALSE;
+ cancel_key = TlsAlloc();
+ if (unlikely(cancel_key == TLS_OUT_OF_INDEXES))
+ {
+ TlsFree(thread_key);
+ return FALSE;
+ }
InitializeCriticalSection (&clock_lock);
vlc_mutex_init (&super_mutex);
vlc_cond_init (&super_variable);
@@ -1043,6 +1072,7 @@ BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
vlc_cond_destroy (&super_variable);
vlc_mutex_destroy (&super_mutex);
DeleteCriticalSection (&clock_lock);
+ TlsFree(cancel_key);
TlsFree(thread_key);
break;
--
2.6.0.windows.1
More information about the vlc-devel
mailing list