Esempio n. 1
0
static void Run          ( intf_thread_t *p_intf )
{
    intf_sys_t    *p_sys = p_intf->p_sys;
    mtime_t        i_last_run = mdate();

    for( ;; )
    {
        int canc = vlc_savecancel();
        vlc_mutex_lock( &p_sys->lock );

        int i_watches = vlc_array_count( p_sys->p_watches );
        struct pollfd *p_fds = calloc( i_watches, sizeof( struct pollfd ) );

        int i_fds = GetPollFds( p_intf, p_fds );

        mtime_t i_now = mdate(), i_loop_interval = i_now - i_last_run;

        msg_Dbg( p_intf,
                 "%lld µs elapsed since last wakeup",
                 (long long) i_loop_interval );

        int i_next_timeout = UpdateTimeouts( p_intf, i_loop_interval );
        i_last_run = i_now;

        vlc_mutex_unlock( &p_sys->lock );

        if( -1 != i_next_timeout )
            msg_Dbg( p_intf, "next timeout is in %d ms", i_next_timeout );
        msg_Dbg( p_intf, "Sleeping until something happens" );

        /* thread cancellation is allowed while the main loop sleeps */
        vlc_restorecancel( canc );

        int i_pollres = poll( p_fds, i_fds, i_next_timeout );
        int i_errsv   = errno;

        canc = vlc_savecancel();

        msg_Dbg( p_intf, "the main loop has been woken up" );

        if( -1 == i_pollres )
        { /* XXX: What should we do when poll() fails ? */
            char buf[64];
            msg_Err( p_intf, "poll() failed: %s", strerror_r( i_errsv, buf, 64 ) );
            free( p_fds ); p_fds = NULL;
            vlc_restorecancel( canc );
            continue;
        }

        /* Was the main loop woken up manually ? */
        if( 0 < i_pollres && ( p_fds[0].revents & POLLIN ) )
        {
            char buf;
            msg_Dbg( p_intf, "Removing a byte from the self-pipe" );
            (void)read( p_fds[0].fd, &buf, 1 );
        }

        /* We need to lock the mutex while building lists of events,
         * timeouts and watches to process but we can't keep the lock while
         * processing them, or else we risk a deadlock:
         *
         * The signal functions could lock mutex X while p_events is locked;
         * While some other function in vlc (playlist) might lock mutex X
         * and then set a variable which would call AllCallback(), which itself
         * needs to lock p_events to add a new event.
         */
        vlc_mutex_lock( &p_intf->p_sys->lock );

        /* Get the list of timeouts to process */
        unsigned int i_timeouts = vlc_array_count( p_sys->p_timeouts );
        DBusTimeout *p_timeouts[i_timeouts];
        for( unsigned int i = 0; i < i_timeouts; i++ )
        {
            p_timeouts[i] = vlc_array_item_at_index( p_sys->p_timeouts, i );
        }

        /* Get the list of watches to process */
        i_watches = vlc_array_count( p_sys->p_watches );
        DBusWatch *p_watches[i_watches];
        for( int i = 0; i < i_watches; i++ )
        {
            p_watches[i] = vlc_array_item_at_index( p_sys->p_watches, i );
        }

        /* Get the list of events to process */
        int i_events = vlc_array_count( p_intf->p_sys->p_events );
        callback_info_t* p_info[i_events];
        for( int i = i_events - 1; i >= 0; i-- )
        {
            p_info[i] = vlc_array_item_at_index( p_intf->p_sys->p_events, i );
            vlc_array_remove( p_intf->p_sys->p_events, i );
        }

        /* now we can release the lock and process what's pending */
        vlc_mutex_unlock( &p_intf->p_sys->lock );

        ProcessEvents( p_intf, p_info, i_events );
        ProcessWatches( p_intf, p_watches, i_watches, p_fds, i_fds );

        free( p_fds ); p_fds = NULL;

        ProcessTimeouts( p_intf, p_timeouts, i_timeouts );
        DispatchDBusMessages( p_intf );

        vlc_restorecancel( canc );
    }
}
Esempio n. 2
0
File: dbus.c Progetto: etix/vlc
static void *Run( void *data )
{
    intf_thread_t *p_intf = data;
    intf_sys_t    *p_sys = p_intf->p_sys;

    int canc = vlc_savecancel();

    for( ;; )
    {
        vlc_mutex_lock( &p_sys->lock );

        int i_watches = vlc_array_count( p_sys->p_watches );
        struct pollfd fds[i_watches];
        memset(fds, 0, sizeof fds);

        int i_fds = GetPollFds( p_intf, fds );
        int timeout = next_timeout(p_intf);

        vlc_mutex_unlock( &p_sys->lock );

        /* thread cancellation is allowed while the main loop sleeps */
        vlc_restorecancel( canc );

        while (poll(fds, i_fds, timeout) == -1)
        {
            if (errno != EINTR)
                goto error;
        }

        canc = vlc_savecancel();

        /* Was the main loop woken up manually ? */
        if (fds[0].revents & POLLIN)
        {
            char buf;
            (void)read( fds[0].fd, &buf, 1 );
        }

        /* We need to lock the mutex while building lists of events,
         * timeouts and watches to process but we can't keep the lock while
         * processing them, or else we risk a deadlock:
         *
         * The signal functions could lock mutex X while p_events is locked;
         * While some other function in vlc (playlist) might lock mutex X
         * and then set a variable which would call AllCallback(), which itself
         * needs to lock p_events to add a new event.
         */
        vlc_mutex_lock( &p_intf->p_sys->lock );

        process_timeouts(p_intf);

        /* Get the list of watches to process */
        i_watches = vlc_array_count( p_sys->p_watches );
        DBusWatch *p_watches[i_watches ? i_watches : 1];
        for( int i = 0; i < i_watches; i++ )
        {
            p_watches[i] = vlc_array_item_at_index( p_sys->p_watches, i );
        }

        /* Get the list of events to process */
        int i_events = vlc_array_count( p_intf->p_sys->p_events );
        callback_info_t* p_info[i_events ? i_events : 1];
        for( int i = i_events - 1; i >= 0; i-- )
        {
            p_info[i] = vlc_array_item_at_index( p_intf->p_sys->p_events, i );
            vlc_array_remove( p_intf->p_sys->p_events, i );
        }

        /* now we can release the lock and process what's pending */
        vlc_mutex_unlock( &p_intf->p_sys->lock );

        ProcessEvents( p_intf, p_info, i_events );
        ProcessWatches( p_intf, p_watches, i_watches, fds, i_fds );

        DispatchDBusMessages( p_intf );
    }
error:
    vlc_restorecancel(canc);
    return NULL;
}