Commit b08e6db9 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

interrupt: add calls to pass interrupt onto another thread

parent 33655fee
......@@ -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
......@@ -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
......
......@@ -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)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment