📄 objects.c
字号:
{ vlc_mutex_lock( &(vlc_internals(obj)->lock) );}void __vlc_object_unlock( vlc_object_t *obj ){ vlc_assert_locked( &(vlc_internals(obj)->lock) ); vlc_mutex_unlock( &(vlc_internals(obj)->lock) );}#ifdef WIN32# include <winsock2.h># include <ws2tcpip.h>/** * select()-able pipes emulated using Winsock */static int pipe (int fd[2]){ SOCKADDR_IN addr; int addrlen = sizeof (addr); SOCKET l = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP), a, c = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); if ((l == INVALID_SOCKET) || (c == INVALID_SOCKET)) goto error; memset (&addr, 0, sizeof (addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); if (bind (l, (PSOCKADDR)&addr, sizeof (addr)) || getsockname (l, (PSOCKADDR)&addr, &addrlen) || listen (l, 1) || connect (c, (PSOCKADDR)&addr, addrlen)) goto error; a = accept (l, NULL, NULL); if (a == INVALID_SOCKET) goto error; closesocket (l); //shutdown (a, 0); //shutdown (c, 1); fd[0] = c; fd[1] = a; return 0;error: if (l != INVALID_SOCKET) closesocket (l); if (c != INVALID_SOCKET) closesocket (c); return -1;}#undef read#define read( a, b, c ) recv (a, b, c, 0)#undef write#define write( a, b, c ) send (a, b, c, 0)#undef close#define close( a ) closesocket (a)#endif /* WIN32 *//** * Returns the readable end of a pipe that becomes readable once termination * of the object is requested (vlc_object_kill()). * This can be used to wake-up out of a select() or poll() event loop, such * typically when doing network I/O. * * Note that the pipe will remain the same for the lifetime of the object. * DO NOT read the pipe nor close it yourself. Ever. * * @param obj object that would be "killed" * @return a readable pipe descriptor, or -1 on error. */int __vlc_object_waitpipe( vlc_object_t *obj ){ int pfd[2] = { -1, -1 }; vlc_object_internals_t *internals = vlc_internals( obj ); bool killed = false; vlc_spin_lock (&internals->spin); if (internals->pipes[0] == -1) { /* This can only ever happen if someone killed us without locking: */ assert (internals->pipes[1] == -1); vlc_spin_unlock (&internals->spin); if (pipe (pfd)) return -1; vlc_spin_lock (&internals->spin); if (internals->pipes[0] == -1) { internals->pipes[0] = pfd[0]; internals->pipes[1] = pfd[1]; pfd[0] = pfd[1] = -1; } killed = obj->b_die; } vlc_spin_unlock (&internals->spin); if (killed) { /* Race condition: vlc_object_kill() already invoked! */ int fd; vlc_spin_lock (&internals->spin); fd = internals->pipes[1]; internals->pipes[1] = -1; vlc_spin_unlock (&internals->spin); msg_Dbg (obj, "waitpipe: object already dying"); if (fd != -1) close (fd); } /* Race condition: two threads call pipe() - unlikely */ if (pfd[0] != -1) close (pfd[0]); if (pfd[1] != -1) close (pfd[1]); return internals->pipes[0];}/** * Waits for the object to be signaled (using vlc_object_signal()). * It is assumed that the caller has locked the object. This function will * unlock the object, and lock it again before returning. * If the object was signaled before the caller locked the object, it is * undefined whether the signal will be lost or will wake the process. * * @return true if the object is dying and should terminate. */void __vlc_object_wait( vlc_object_t *obj ){ vlc_object_internals_t *priv = vlc_internals( obj ); vlc_assert_locked( &priv->lock); vlc_cond_wait( &priv->wait, &priv->lock );}/** * Waits for the object to be signaled (using vlc_object_signal()), or for * a timer to expire. It is asserted that the caller holds the object lock. * * @return 0 if the object was signaled before the timer expiration, or * ETIMEDOUT if the timer expired without any signal. */int __vlc_object_timedwait( vlc_object_t *obj, mtime_t deadline ){ vlc_object_internals_t *priv = vlc_internals( obj ); vlc_assert_locked( &priv->lock); return vlc_cond_timedwait( &priv->wait, &priv->lock, deadline );}/** * Signals an object for which the lock is held. * At least one thread currently sleeping in vlc_object_wait() or * vlc_object_timedwait() will wake up, assuming that there is at least one * such thread in the first place. Otherwise, it is undefined whether the * signal will be lost or will wake up one or more thread later. */void __vlc_object_signal_unlocked( vlc_object_t *obj ){ vlc_assert_locked (&(vlc_internals(obj)->lock)); vlc_cond_signal( &(vlc_internals(obj)->wait) );}/** * Requests termination of an object. * If the object is LibVLC, also request to terminate all its children. */void __vlc_object_kill( vlc_object_t *p_this ){ vlc_object_internals_t *priv = vlc_internals( p_this ); int fd; vlc_object_lock( p_this ); p_this->b_die = true; vlc_spin_lock (&priv->spin); fd = priv->pipes[1]; priv->pipes[1] = -1; vlc_spin_unlock (&priv->spin); if( fd != -1 ) { msg_Dbg (p_this, "waitpipe: object killed"); close (fd); } vlc_object_signal_unlocked( p_this ); /* This also serves as a memory barrier toward vlc_object_alive(): */ vlc_object_unlock( p_this );}/** * Find an object given its ID. * * This function looks for the object whose i_object_id field is i_id. * This function is slow, and often used to hide bugs. Do not use it. * If you need to retain reference to an object, yield the object pointer with * vlc_object_yield(), use the pointer as your reference, and call * vlc_object_release() when you're done. */void * vlc_object_get( int i_id ){ libvlc_global_data_t *p_libvlc_global = vlc_global(); vlc_object_t *obj = NULL;#ifndef NDEBUG vlc_object_t *caller = vlc_threadobj (); if (caller) msg_Dbg (caller, "uses deprecated vlc_object_get(%d)", i_id); else fprintf (stderr, "main thread uses deprecated vlc_object_get(%d)\n", i_id);#endif vlc_mutex_lock( &structure_lock ); for( obj = vlc_internals (p_libvlc_global)->next; obj != VLC_OBJECT (p_libvlc_global); obj = vlc_internals (obj)->next ) { if( obj->i_object_id == i_id ) { vlc_object_yield( obj ); goto out; } } obj = NULL;#ifndef NDEBUG if (caller) msg_Warn (caller, "wants non-existing object %d", i_id); else fprintf (stderr, "main thread wants non-existing object %d\n", i_id);#endifout: vlc_mutex_unlock( &structure_lock ); return obj;}/** **************************************************************************** * find a typed object and increment its refcount ***************************************************************************** * This function recursively looks for a given object type. i_mode can be one * of FIND_PARENT, FIND_CHILD or FIND_ANYWHERE. *****************************************************************************/void * __vlc_object_find( vlc_object_t *p_this, int i_type, int i_mode ){ vlc_object_t *p_found; /* If we are of the requested type ourselves, don't look further */ if( !(i_mode & FIND_STRICT) && p_this->i_object_type == i_type ) { vlc_object_yield( p_this ); return p_this; } /* Otherwise, recursively look for the object */ if ((i_mode & 0x000f) == FIND_ANYWHERE) {#ifndef NDEBUG if (i_type == VLC_OBJECT_PLAYLIST) msg_Err (p_this, "using vlc_object_find(VLC_OBJECT_PLAYLIST) " "instead of pl_Yield()");#endif return vlc_object_find (p_this->p_libvlc, i_type, (i_mode & ~0x000f)|FIND_CHILD); } vlc_mutex_lock( &structure_lock ); p_found = FindObject( p_this, i_type, i_mode ); vlc_mutex_unlock( &structure_lock ); return p_found;}/** **************************************************************************** * find a named object and increment its refcount ***************************************************************************** * This function recursively looks for a given object name. i_mode can be one * of FIND_PARENT, FIND_CHILD or FIND_ANYWHERE. *****************************************************************************/void * __vlc_object_find_name( vlc_object_t *p_this, const char *psz_name, int i_mode ){ vlc_object_t *p_found; /* If have the requested name ourselves, don't look further */ if( !(i_mode & FIND_STRICT) && p_this->psz_object_name && !strcmp( p_this->psz_object_name, psz_name ) ) { vlc_object_yield( p_this ); return p_this; } vlc_mutex_lock( &structure_lock ); /* Otherwise, recursively look for the object */ if( (i_mode & 0x000f) == FIND_ANYWHERE ) { vlc_object_t *p_root = p_this; /* Find the root */ while( p_root->p_parent != NULL && p_root != VLC_OBJECT( p_this->p_libvlc ) ) { p_root = p_root->p_parent; } p_found = FindObjectName( p_root, psz_name, (i_mode & ~0x000f)|FIND_CHILD ); if( p_found == NULL && p_root != VLC_OBJECT( p_this->p_libvlc ) ) { p_found = FindObjectName( VLC_OBJECT( p_this->p_libvlc ), psz_name, (i_mode & ~0x000f)|FIND_CHILD ); } } else { p_found = FindObjectName( p_this, psz_name, i_mode ); } vlc_mutex_unlock( &structure_lock ); return p_found;}/** * Increment an object reference counter. */void __vlc_object_yield( vlc_object_t *p_this ){ vlc_object_internals_t *internals = vlc_internals( p_this ); vlc_spin_lock( &internals->ref_spin ); /* Avoid obvious freed object uses */ assert( internals->i_refcount > 0 ); /* Increment the counter */ internals->i_refcount++; vlc_spin_unlock( &internals->ref_spin );#ifdef LIBVLC_REFCHECK /* Update the list of referenced objects */ /* Using TLS, so no need to lock */ /* The following line may leak memory if a thread leaks objects. */ held_list_t *newhead = malloc (sizeof (*newhead)); held_list_t *oldhead = vlc_threadvar_get (&held_objects); newhead->next = oldhead; newhead->obj = p_this; vlc_threadvar_set (&held_objects, newhead);#endif}/***************************************************************************** * decrement an object refcount * And destroy the object if its refcount reach zero. *****************************************************************************/void __vlc_object_release( vlc_object_t *p_this ){ vlc_object_internals_t *internals = vlc_internals( p_this ); bool b_should_destroy;#ifdef LIBVLC_REFCHECK /* Update the list of referenced objects */ /* Using TLS, so no need to lock */ for (held_list_t *hlcur = vlc_threadvar_get (&held_objects), *hlprev = NULL; hlcur != NULL; hlprev = hlcur, hlcur = hlcur->next) { if (hlcur->obj == p_this) { if (hlprev == NULL) vlc_threadvar_set (&held_objects, hlcur->next); else hlprev->next = hlcur->next; free (hlcur); break; } } /* TODO: what if releasing without references? */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -