vlc | branch: master | Rémi Denis-Courmont <[email protected]> | Sat Aug 29 12:39:35 2015 +0300| [b08e6db9a9debbd85acf410fc018a222e84dd035] | committer: Rémi Denis-Courmont
interrupt: add calls to pass interrupt onto another thread > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=b08e6db9a9debbd85acf410fc018a222e84dd035 --- include/vlc_interrupt.h | 36 ++++++++++++++++++++++++++++++++++++ src/libvlccore.sym | 2 ++ src/misc/interrupt.c | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/include/vlc_interrupt.h b/include/vlc_interrupt.h index b4aba1c..46c4195 100644 --- a/include/vlc_interrupt.h +++ b/include/vlc_interrupt.h @@ -189,5 +189,41 @@ VLC_API void vlc_interrupt_kill(vlc_interrupt_t *); */ VLC_API bool vlc_killed(void) VLC_USED; +/** + * Enables forwarding of interruption. + * + * If an interruption is raised through the context of the calling thread, + * it will be forwarded to the specified other context. This is used to cross + * thread boundaries. + * + * If the calling thread already has an interruption pending, this function + * dequeues the interrupt, return an error code and does not enable forwarding. + * + * If the calling thread has no interrupt context, this function does nothing + * and returns zero. + * + * @param to context to forward to + * @return 0 on success, or EINTR on error + */ +VLC_API int vlc_interrupt_forward_start(vlc_interrupt_t *to, + void *data[2]) VLC_USED; + +/** + * Undoes vlc_interrupt_forward_start(). + * + * This function must be called after each succesful call to + * vlc_interrupt_forward_start() before any other interruptible call is made + * in the same thread. + * + * If an interruption was raised against the context of the calling thread + * (after the previous call to vlc_interrupt_forward_start()), it is dequeued. + * + * If the calling thread has no interrupt context, this function does nothing + * and returns zero. + * + * @return 0 if no interrupt was raised, EINTR if an interrupt was raised + */ +VLC_API int vlc_interrupt_forward_stop(void *const data[2]); + /** @} @} */ #endif diff --git a/src/libvlccore.sym b/src/libvlccore.sym index 1ee6ecc..0a37042 100644 --- a/src/libvlccore.sym +++ b/src/libvlccore.sym @@ -562,6 +562,8 @@ vlc_interrupt_destroy vlc_interrupt_set vlc_interrupt_raise vlc_interrupt_kill +vlc_interrupt_forward_start +vlc_interrupt_forward_stop vlc_killed vlc_join vlc_list_children diff --git a/src/misc/interrupt.c b/src/misc/interrupt.c index 08d5d81..c2a07d2 100644 --- a/src/misc/interrupt.c +++ b/src/misc/interrupt.c @@ -302,6 +302,41 @@ int vlc_mwait_i11e(mtime_t deadline) return ret; } +static void vlc_interrupt_forward_wake(void *opaque) +{ + void **data = opaque; + vlc_interrupt_t *to = data[0]; + vlc_interrupt_t *from = data[1]; + + (atomic_load(&from->killed) ? vlc_interrupt_kill + : vlc_interrupt_raise)(to); +} + +int vlc_interrupt_forward_start(vlc_interrupt_t *to, void *data[2]) +{ + data[0] = data[1] = NULL; + + vlc_interrupt_t *from = vlc_threadvar_get(vlc_interrupt_var); + if (from == NULL) + return 0; + + assert(from != to); + data[0] = to; + data[1] = from; + return vlc_interrupt_prepare(from, vlc_interrupt_forward_wake, data); +} + +int vlc_interrupt_forward_stop(void *const data[2]) +{ + vlc_interrupt_t *from = data[1]; + if (from == NULL) + return 0; + + assert(from->callback == vlc_interrupt_forward_wake); + assert(from->data == data); + return vlc_interrupt_finish(from); +} + #ifndef _WIN32 static void vlc_poll_i11e_wake(void *opaque) { _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
