[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