vlc | branch: master | Rémi Denis-Courmont <[email protected]> | Sun Dec 13 16:35:31 2015 +0200| [9ee0adc8e44916eb69eedb3620e9d836db643144] | committer: Rémi Denis-Courmont
interrupt: add support for custom callbacks It seems impossible to handle interruptions while waiting on a condition variable otherwise. In particular, a single vlc_cond_wait_i11e() function would be intrinsically prone to deadlocks: - It would need to acquire the interrupt context lock while the caller already holds the mutex corresponding to the condition variable, but - the interrupt callback would need to acquire the mutex while holding the interrupt context lock. This would be a classic lock inversion race. This addition should also enable hooking with other libraries, such as Glib´s GCancellable. Be very careful when using these two new functions. VLC does not support stacking interrupt handlers (at least not currently). So there MUST NOT be any call to another interruptible function between vlc_interrupt_register() and vlc_interrupt_unregister(). > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=9ee0adc8e44916eb69eedb3620e9d836db643144 --- include/vlc_interrupt.h | 14 ++++++++++++++ src/libvlccore.sym | 2 ++ src/misc/interrupt.c | 13 +++++++++++++ 3 files changed, 29 insertions(+) diff --git a/include/vlc_interrupt.h b/include/vlc_interrupt.h index 84e4585..f45e048 100644 --- a/include/vlc_interrupt.h +++ b/include/vlc_interrupt.h @@ -137,6 +137,20 @@ ssize_t vlc_send_i11e(int fd, const void *buf, size_t len, int flags) VLC_API int vlc_accept_i11e(int fd, struct sockaddr *, socklen_t *, bool); /** + * Registers a custom interrupt handler. + * + * Registers a custom callback as interrupt handler for the calling thread. + * The callback must be unregistered with vlc_interrupt_unregister() before + * thread termination and before any further callback registration. + * + * If the calling thread has no interruption context, this function has no + * effects. + */ +VLC_API void vlc_interrupt_register(void (*cb)(void *), void *opaque); + +VLC_API int vlc_interrupt_unregister(void); + +/** * @} * @defgroup interrupt_context Interrupt context signaling and manipulation * @{ diff --git a/src/libvlccore.sym b/src/libvlccore.sym index 95152e8..d7971d8 100644 --- a/src/libvlccore.sym +++ b/src/libvlccore.sym @@ -566,6 +566,8 @@ vlc_interrupt_raise vlc_interrupt_kill vlc_interrupt_forward_start vlc_interrupt_forward_stop +vlc_interrupt_register +vlc_interrupt_unregister vlc_killed vlc_join vlc_list_children diff --git a/src/misc/interrupt.c b/src/misc/interrupt.c index 68c0364..6560ba1 100644 --- a/src/misc/interrupt.c +++ b/src/misc/interrupt.c @@ -203,6 +203,19 @@ static int vlc_interrupt_finish(vlc_interrupt_t *ctx) return ret; } +void vlc_interrupt_register(void (*cb)(void *), void *opaque) +{ + vlc_interrupt_t *ctx = vlc_threadvar_get(vlc_interrupt_var); + if (ctx != NULL) + vlc_interrupt_prepare(ctx, cb, opaque); +} + +int vlc_interrupt_unregister(void) +{ + vlc_interrupt_t *ctx = vlc_threadvar_get(vlc_interrupt_var); + return (ctx != NULL) ? vlc_interrupt_finish(ctx) : 0; +} + static void vlc_interrupt_cleanup(void *opaque) { vlc_interrupt_finish(opaque); _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
