static void vlc_thread_cleanup (struct vlc_thread *th) { vlc_threadvar_t key; retry: /* TODO: use RW lock or something similar */ vlc_mutex_lock (&super_mutex); for (key = vlc_threadvar_last; key != NULL; key = key->prev) { void *value = vlc_threadvar_get (key); if (value != NULL && key->destroy != NULL) { vlc_mutex_unlock (&super_mutex); vlc_threadvar_set (key, NULL); key->destroy (value); goto retry; } } vlc_mutex_unlock (&super_mutex); if (th->detached) { CloseHandle (th->id); free (th); } }
vlc_interrupt_t *vlc_interrupt_set(vlc_interrupt_t *newctx) { vlc_interrupt_t *oldctx; /* This function is called to push or pop an interrupt context. Either way * either newctx or oldctx (or both) are non-NULL. Thus vlc_interrupt_refs * must be larger than zero and vlc_interrupt_var must be valid. And so the * read/write lock is not needed. */ assert(vlc_interrupt_refs > 0); oldctx = vlc_threadvar_get(vlc_interrupt_var); #ifndef NDEBUG if (oldctx != NULL) { assert(oldctx->attached); oldctx->attached = false; } if (newctx != NULL) { assert(!newctx->attached); newctx->attached = true; } #endif vlc_threadvar_set(vlc_interrupt_var, newctx); return oldctx; }
/************************************************************************** * event_async_loop (private) : * * Send queued events. **************************************************************************/ static void * event_async_loop(void * arg) { libvlc_event_manager_t * p_em = arg; libvlc_event_listener_t listener; libvlc_event_t event; vlc_threadvar_set(queue(p_em)->is_asynch_dispatch_thread_var, p_em); queue_lock(p_em); while (true) { int has_listener = pop(p_em, &listener, &event); if (has_listener) { queue_unlock(p_em); listener.pf_callback(&event, listener.p_user_data); // This might edit the queue queue_lock(p_em); } else { queue(p_em)->is_idle = true; mutex_cleanup_push(&queue(p_em)->lock); vlc_cond_broadcast(&queue(p_em)->signal_idle); // We'll be idle vlc_cond_wait(&queue(p_em)->signal, &queue(p_em)->lock); vlc_cleanup_pop(); queue(p_em)->is_idle = false; } } queue_unlock(p_em); return NULL; }
static unsigned __stdcall vlc_entry (void *p) { struct vlc_thread *th = (vlc_thread *)p; // sunqueen modify vlc_threadvar_set (thread_key, th); th->killable = true; th->data = th->entry (th->data); vlc_thread_cleanup (th); return 0; }
static void vlc_entry( void *p ) { struct vlc_thread *th = p; vlc_threadvar_set (thread_key, th); th->killable = true; th->data = th->entry (th->data); DosPostEventSem( th->done_event ); vlc_thread_cleanup (th); }
static msg_context_t* GetContext(void) { msg_context_t *p_ctx = vlc_threadvar_get( &msg_context_global_key ); if( p_ctx == NULL ) { MALLOC_NULL( p_ctx, msg_context_t ); p_ctx->psz_message = NULL; vlc_threadvar_set( &msg_context_global_key, p_ctx ); } return p_ctx; }
/*** Threads ***/ static unsigned __stdcall vlc_entry (void *data) { vlc_cancel_t cancel_data = VLC_CANCEL_INIT; vlc_thread_t self = data; #ifdef UNDER_CE cancel_data.cancel_event = self->cancel_event; #endif vlc_threadvar_set (cancel_key, &cancel_data); self->data = self->entry (self->data); return 0; }
/** * Sets the LibVLC error status and message for the current thread. * Any previous error is overridden. * @return a nul terminated string (always) */ const char *libvlc_vprinterr (const char *fmt, va_list ap) { char *msg; assert (fmt != NULL); if (vasprintf (&msg, fmt, ap) == -1) msg = (char *)oom; free_error (); vlc_threadvar_set (context, msg); return msg; }
static msg_context_t* GetContext(void) { msg_context_t *p_ctx = vlc_threadvar_get( msg_context ); if( p_ctx == NULL ) { p_ctx = malloc( sizeof( msg_context_t ) ); if( !p_ctx ) return NULL; p_ctx->psz_message = NULL; vlc_threadvar_set( msg_context, p_ctx ); } return p_ctx; }
static THREAD_RTYPE thread_entry (void *data) { vlc_object_t *obj = ((struct vlc_thread_boot *)data)->object; void *(*func) (vlc_object_t *) = ((struct vlc_thread_boot *)data)->entry; free (data); #ifndef NDEBUG vlc_threadvar_set (&thread_object_key, obj); #endif msg_Dbg (obj, "thread started"); func (obj); msg_Dbg (obj, "thread ended"); return THREAD_RVAL; }
static void vlc_threadvars_cleanup(void) { vlc_threadvar_t key; retry: /* TODO: use RW lock or something similar */ vlc_mutex_lock(&super_mutex); for (key = vlc_threadvar_last; key != NULL; key = key->prev) { void *value = vlc_threadvar_get(key); if (value != NULL && key->destroy != NULL) { vlc_mutex_unlock(&super_mutex); vlc_threadvar_set(key, NULL); key->destroy(value); goto retry; } } vlc_mutex_unlock(&super_mutex); }
vlc_interrupt_t *vlc_interrupt_set(vlc_interrupt_t *newctx) { vlc_interrupt_t *oldctx; oldctx = vlc_threadvar_get(vlc_interrupt_var); #ifndef NDEBUG if (oldctx != NULL) { assert(oldctx->attached); oldctx->attached = false; } if (newctx != NULL) { assert(!newctx->attached); newctx->attached = true; } #endif vlc_threadvar_set(vlc_interrupt_var, newctx); return oldctx; }
/** * Clears the LibVLC error status for the current thread. This is optional. * By default, the error status is automatically overridden when a new error * occurs, and destroyed when the thread exits. */ void libvlc_clearerr (void) { free_error (); vlc_threadvar_set (context, NULL); }