[vlc-commits] interrupt: add calls to pass interrupt onto another thread
Rémi Denis-Courmont
git at videolan.org
Sat Aug 29 13:59:40 CEST 2015
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | 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)
{
More information about the vlc-commits
mailing list