static void BackgroundWorkerCancel( struct background_worker* worker, void* id) { vlc_mutex_lock( &worker->lock ); for( size_t i = 0; i < vlc_array_count( &worker->tail.data ); ) { struct bg_queued_item* item = vlc_array_item_at_index( &worker->tail.data, i ); if( id == NULL || item->id == id ) { vlc_array_remove( &worker->tail.data, i ); worker->conf.pf_release( item->entity ); free( item ); continue; } ++i; } while( ( id == NULL && worker->head.active ) || ( id != NULL && worker->head.id == id ) ) { worker->head.deadline = VLC_TS_0; vlc_cond_signal( &worker->head.worker_wait ); vlc_cond_signal( &worker->tail.wait ); vlc_cond_wait( &worker->head.wait, &worker->lock ); } vlc_mutex_unlock( &worker->lock ); }
static void Run ( intf_thread_t *p_intf ) { for( ;; ) { if( dbus_connection_get_dispatch_status(p_intf->p_sys->p_conn) == DBUS_DISPATCH_COMPLETE ) msleep( INTF_IDLE_SLEEP ); int canc = vlc_savecancel(); dbus_connection_read_write_dispatch( p_intf->p_sys->p_conn, 0 ); /* Get the list of events to process * * We can't keep the lock on p_intf->p_sys->p_events, 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 ); int i_events = vlc_array_count( p_intf->p_sys->p_events ); callback_info_t* info[i_events]; for( int i = i_events - 1; i >= 0; i-- ) { info[i] = vlc_array_item_at_index( p_intf->p_sys->p_events, i ); vlc_array_remove( p_intf->p_sys->p_events, i ); } vlc_mutex_unlock( &p_intf->p_sys->lock ); for( int i = 0; i < i_events; i++ ) { switch( info[i]->signal ) { case SIGNAL_ITEM_CURRENT: TrackChange( p_intf ); break; case SIGNAL_INTF_CHANGE: case SIGNAL_PLAYLIST_ITEM_APPEND: case SIGNAL_PLAYLIST_ITEM_DELETED: TrackListChangeEmit( p_intf, info[i]->signal, info[i]->i_node ); break; case SIGNAL_RANDOM: case SIGNAL_REPEAT: case SIGNAL_LOOP: StatusChangeEmit( p_intf ); break; case SIGNAL_STATE: StateChange( p_intf, info[i]->i_input_state ); break; default: assert(0); } free( info[i] ); } vlc_restorecancel( canc ); } }
static void remove_timeout(DBusTimeout *to, void *data) { intf_thread_t *intf = data; intf_sys_t *sys = intf->p_sys; unsigned idx = vlc_array_index_of_item(sys->p_timeouts, to); vlc_mutex_lock(&sys->lock); vlc_array_remove(sys->p_timeouts, idx); vlc_mutex_unlock(&sys->lock); }
static void remove_watch( DBusWatch *p_watch, void *p_data ) { intf_thread_t *p_intf = (intf_thread_t*) p_data; intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys; vlc_mutex_lock( &p_sys->lock ); vlc_array_remove( p_sys->p_watches, vlc_array_index_of_item( p_sys->p_watches, p_watch ) ); vlc_mutex_unlock( &p_sys->lock ); }
static void remove_timeout( DBusTimeout *p_timeout, void *p_data ) { intf_thread_t *p_intf = (intf_thread_t*) p_data; intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys; vlc_mutex_lock( &p_sys->lock ); vlc_array_remove( p_sys->p_timeouts, vlc_array_index_of_item( p_sys->p_timeouts, p_timeout ) ); vlc_mutex_unlock( &p_sys->lock ); }
/************************************************************************** * libvlc_event_detach (public) : * * Remove a callback for an event. **************************************************************************/ void libvlc_event_detach( libvlc_event_manager_t *p_event_manager, libvlc_event_type_t event_type, libvlc_callback_t pf_callback, void *p_user_data ) { libvlc_event_listeners_group_t * listeners_group; libvlc_event_listener_t * listener; int i, j; bool found = false; vlc_mutex_lock( &p_event_manager->event_sending_lock ); vlc_mutex_lock( &p_event_manager->object_lock ); for( i = 0; i < vlc_array_count(&p_event_manager->listeners_groups); i++) { listeners_group = vlc_array_item_at_index(&p_event_manager->listeners_groups, i); if( listeners_group->event_type == event_type ) { for( j = 0; j < vlc_array_count(&listeners_group->listeners); j++) { listener = vlc_array_item_at_index(&listeners_group->listeners, j); if( listener->event_type == event_type && listener->pf_callback == pf_callback && listener->p_user_data == p_user_data ) { /* that's our listener */ /* Mark this group as edited so that libvlc_event_send * will recheck what listener to call */ listeners_group->b_sublistener_removed = true; free( listener ); vlc_array_remove( &listeners_group->listeners, j ); found = true; break; } } } } vlc_mutex_unlock( &p_event_manager->object_lock ); vlc_mutex_unlock( &p_event_manager->event_sending_lock ); /* Now make sure any pending async event won't get fired after that point */ libvlc_event_listener_t listener_to_remove; listener_to_remove.event_type = event_type; listener_to_remove.pf_callback = pf_callback; listener_to_remove.p_user_data = p_user_data; listener_to_remove.is_asynchronous = true; libvlc_event_async_ensure_listener_removal(p_event_manager, &listener_to_remove); assert(found); }
static fingerprint_request_t * GetResult( fingerprinter_thread_t *f ) { fingerprint_request_t *r = NULL; fingerprinter_sys_t *p_sys = f->p_sys; vlc_mutex_lock( &p_sys->results.lock ); if ( vlc_array_count( &p_sys->results.queue ) ) { r = vlc_array_item_at_index( &p_sys->results.queue, 0 ); vlc_array_remove( &p_sys->results.queue, 0 ); } vlc_mutex_unlock( &p_sys->results.lock ); return r; }
/************************************************************************** * ml_item_removed (private) (Callback from media_list_view) **************************************************************************/ static void ml_item_removed( const libvlc_event_t * p_event, libvlc_media_list_view_t * p_mlv ) { libvlc_media_t * p_md = p_event->u.media_list_item_deleted.item; int i = vlc_array_index_of_item( &p_mlv->p_this_view_data->array, p_md ); if( i >= 0 ) { libvlc_media_list_view_will_delete_item( p_mlv, p_md, i ); vlc_array_remove( &p_mlv->p_this_view_data->array, i ); libvlc_media_list_view_item_deleted( p_mlv, p_md, i ); libvlc_media_release( p_md ); } }
static void remove_watch( DBusWatch *p_watch, void *p_data ) { intf_thread_t *p_intf = (intf_thread_t*) p_data; intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys; msg_Dbg( p_intf, "Removing dbus watch on fd %d", dbus_watch_get_unix_fd( p_watch ) ); vlc_mutex_lock( &p_sys->lock ); vlc_array_remove( p_sys->p_watches, vlc_array_index_of_item( p_sys->p_watches, p_watch ) ); vlc_mutex_unlock( &p_sys->lock ); }
static void dialog_remove_locked(vlc_dialog_provider *p_provider, vlc_dialog_id *p_id) { ssize_t i_idx = vlc_array_index_of_item(&p_provider->dialog_array, p_id); assert(i_idx >= 0); vlc_array_remove(&p_provider->dialog_array, i_idx); vlc_mutex_lock(&p_id->lock); p_id->i_refcount--; if (p_id->i_refcount == 0) { vlc_mutex_unlock(&p_id->lock); dialog_id_release(p_id); } else vlc_mutex_unlock(&p_id->lock); }
bool vlc_http_cookies_store(vlc_http_cookie_jar_t *p_jar, const char *cookies, bool secure, const char *host, const char *path) { assert(host != NULL); assert(path != NULL); int i; http_cookie_t *cookie = cookie_parse(cookies, host, path); if (cookie == NULL) return false; if (!cookie_is_valid(cookie, secure, host, path)) { cookie_destroy(cookie); return false; } vlc_mutex_lock( &p_jar->lock ); for( i = 0; i < vlc_array_count( &p_jar->cookies ); i++ ) { http_cookie_t *iter = vlc_array_item_at_index( &p_jar->cookies, i ); assert( iter->psz_name ); assert( iter->psz_domain ); assert( iter->psz_path ); bool domains_match = vlc_ascii_strcasecmp( cookie->psz_domain, iter->psz_domain ) == 0; bool paths_match = strcmp( cookie->psz_path, iter->psz_path ) == 0; bool names_match = strcmp( cookie->psz_name, iter->psz_name ) == 0; if( domains_match && paths_match && names_match ) { /* Remove previous value for this cookie */ vlc_array_remove( &p_jar->cookies, i ); cookie_destroy(iter); break; } } vlc_array_append( &p_jar->cookies, cookie ); vlc_mutex_unlock( &p_jar->lock ); return true; }
static void entry_item_remove( services_discovery_t *p_sd, netbios_ns_entry *p_entry ) { services_discovery_sys_t *p_sys = p_sd->p_sys; for ( int i = 0; i < vlc_array_count( p_sys->p_entry_item_list ); i++ ) { struct entry_item *p_entry_item; p_entry_item = vlc_array_item_at_index( p_sys->p_entry_item_list, i ); if( p_entry_item->p_entry == p_entry ) { services_discovery_RemoveItem( p_sd, p_entry_item->p_item ); vlc_gc_decref( p_entry_item->p_item ); vlc_array_remove( p_sys->p_entry_item_list, i ); free( p_entry_item ); break; } } }
/* LibVLC internal version */ void _libvlc_media_list_remove_index( libvlc_media_list_t * p_mlist, int index, libvlc_exception_t * p_e ) { libvlc_media_t * p_md; if( index < 0 || index >= vlc_array_count( &p_mlist->items )) { libvlc_exception_raise( p_e, "Index out of bounds"); return; } p_md = vlc_array_item_at_index( &p_mlist->items, index ); notify_item_deletion( p_mlist, p_md, index, EventWillHappen ); vlc_array_remove( &p_mlist->items, index ); notify_item_deletion( p_mlist, p_md, index, EventDidHappen ); libvlc_media_release( p_md ); }
/* LibVLC internal version */ int libvlc_media_list_internal_remove_index( libvlc_media_list_t * p_mlist, int index ) { libvlc_media_t * p_md; if( index < 0 || index >= vlc_array_count( &p_mlist->items )) { libvlc_printerr( "Index out of bounds" ); return -1; } p_md = vlc_array_item_at_index( &p_mlist->items, index ); notify_item_deletion( p_mlist, p_md, index, EventWillHappen ); vlc_array_remove( &p_mlist->items, index ); notify_item_deletion( p_mlist, p_md, index, EventDidHappen ); libvlc_media_release( p_md ); return 0; }
/************************************************************************** * libvlc_event_detach (public) : * * Remove a callback for an event. **************************************************************************/ void libvlc_event_detach(libvlc_event_manager_t *em, libvlc_event_type_t type, libvlc_callback_t callback, void *opaque) { vlc_mutex_lock(&em->lock); for (size_t i = 0; i < vlc_array_count(&em->listeners); i++) { libvlc_event_listener_t *listener; listener = vlc_array_item_at_index(&em->listeners, i); if (listener->event_type == type && listener->pf_callback == callback && listener->p_user_data == opaque) { /* that's our listener */ vlc_array_remove(&em->listeners, i); vlc_mutex_unlock(&em->lock); free(listener); return; } } abort(); }
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 ); } }
static void* Thread( void* data ) { struct background_worker* worker = data; for( ;; ) { struct bg_queued_item* item = NULL; void* handle; vlc_mutex_lock( &worker->lock ); for( ;; ) { if( vlc_array_count( &worker->tail.data ) ) { item = vlc_array_item_at_index( &worker->tail.data, 0 ); handle = NULL; vlc_array_remove( &worker->tail.data, 0 ); } if( worker->head.deadline == VLC_TS_0 && item == NULL ) worker->head.active = false; worker->head.id = item ? item->id : NULL; vlc_cond_broadcast( &worker->head.wait ); if( item ) { if( item->timeout > 0 ) worker->head.deadline = mdate() + item->timeout * 1000; else worker->head.deadline = INT64_MAX; } else if( worker->head.deadline != VLC_TS_0 ) { /* Wait 1 seconds for new inputs before terminating */ mtime_t deadline = mdate() + INT64_C(1000000); int ret = vlc_cond_timedwait( &worker->tail.wait, &worker->lock, deadline ); if( ret != 0 ) { /* Timeout: if there is still no items, the thread will be * terminated at next loop iteration (active = false). */ worker->head.deadline = VLC_TS_0; } continue; } break; } if( !worker->head.active ) { vlc_mutex_unlock( &worker->lock ); break; } vlc_mutex_unlock( &worker->lock ); assert( item != NULL ); if( worker->conf.pf_start( worker->owner, item->entity, &handle ) ) { worker->conf.pf_release( item->entity ); free( item ); continue; } for( ;; ) { vlc_mutex_lock( &worker->lock ); bool const b_timeout = worker->head.deadline <= mdate(); worker->head.probe_request = false; vlc_mutex_unlock( &worker->lock ); if( b_timeout || worker->conf.pf_probe( worker->owner, handle ) ) { worker->conf.pf_stop( worker->owner, handle ); worker->conf.pf_release( item->entity ); free( item ); break; } vlc_mutex_lock( &worker->lock ); if( worker->head.probe_request == false && worker->head.deadline > mdate() ) { vlc_cond_timedwait( &worker->head.worker_wait, &worker->lock, worker->head.deadline ); } vlc_mutex_unlock( &worker->lock ); } } return NULL; }
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; }