#include "vlc_codec.h"
#include "variables.h"
+
+#ifdef HAVE_SEARCH_H
+# include <search.h>
+#endif
+
#ifndef WIN32
+# include <vlc_fs.h>
# include <unistd.h>
#else
# include <io.h>
# define close( a ) closesocket (a)
#endif
-#include <search.h>
#include <limits.h>
#include <assert.h>
#if defined (HAVE_SYS_EVENTFD_H)
# include <sys/eventfd.h>
+# ifndef EFD_CLOEXEC
+# define EFD_CLOEXEC 0
+# warning EFD_CLOEXEC missing. Consider updating libc.
+# endif
#endif
static int DumpCommand( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
-static vlc_object_t * FindParent ( vlc_object_t *, int );
-static vlc_object_t * FindChild ( vlc_object_internals_t *, int );
static vlc_object_t * FindParentName( vlc_object_t *, const char * );
static vlc_object_t * FindChildName ( vlc_object_internals_t *, const char * );
static void PrintObject( vlc_object_internals_t *, const char * );
static vlc_list_t * NewList ( int );
static void vlc_object_destroy( vlc_object_t *p_this );
-static void vlc_object_detach_unlocked (vlc_object_t *p_this);
/*****************************************************************************
* Local structure lock
vlc_mutex_unlock (&(libvlc_priv (p_libvlc)->structure_lock));
}
-void *__vlc_custom_create( vlc_object_t *p_this, size_t i_size,
- int i_type, const char *psz_type )
+#undef vlc_custom_create
+void *vlc_custom_create( vlc_object_t *p_this, size_t i_size,
+ int i_type, const char *psz_type )
{
vlc_object_t *p_new;
vlc_object_internals_t *p_priv;
p_priv->b_thread = false;
p_new->p_parent = NULL;
p_priv->first = NULL;
-#ifndef NDEBUG
- p_priv->old_parent = NULL;
-#endif
/* Initialize mutexes and condvars */
vlc_mutex_init( &p_priv->var_lock );
return vlc_custom_create( p_this, i_size, VLC_OBJECT_GENERIC, "generic" );
}
-
+#undef vlc_object_set_destructor
/**
****************************************************************************
* Set the destructor of a vlc object
* when the object is destroyed when the its refcount reaches 0.
* (It is called by the internal function vlc_object_destroy())
*****************************************************************************/
-void __vlc_object_set_destructor( vlc_object_t *p_this,
- vlc_destructor_t pf_destructor )
+void vlc_object_set_destructor( vlc_object_t *p_this,
+ vlc_destructor_t pf_destructor )
{
vlc_object_internals_t *p_priv = vlc_internals(p_this );
{
vlc_object_internals_t *p_priv = vlc_internals( p_this );
- /* Objects are always detached beforehand */
- assert( !p_this->p_parent );
-
/* Send a kill to the object's thread if applicable */
vlc_object_kill( p_this );
/**
* select()-able pipes emulated using Winsock
*/
-static int pipe (int fd[2])
+# define vlc_pipe selectable_pipe
+static int selectable_pipe (int fd[2])
{
SOCKADDR_IN addr;
int addrlen = sizeof (addr);
/* This can only ever happen if someone killed us without locking: */
assert (internals->pipes[1] == -1);
+ /* pipe() is not a cancellation point, but write() is and eventfd() is
+ * unspecified (not in POSIX). */
+ int canc = vlc_savecancel ();
#if defined (HAVE_SYS_EVENTFD_H)
- internals->pipes[0] = internals->pipes[1] = eventfd (0, 0);
+ internals->pipes[0] = internals->pipes[1] = eventfd (0, EFD_CLOEXEC);
if (internals->pipes[0] == -1)
#endif
{
- if (pipe (internals->pipes))
+ if (vlc_pipe (internals->pipes))
internals->pipes[0] = internals->pipes[1] = -1;
}
msg_Dbg (obj, "waitpipe: object already dying");
write (internals->pipes[1], &(uint64_t){ 1 }, sizeof (uint64_t));
}
+ vlc_restorecancel (canc);
}
vlc_mutex_unlock (&pipe_lock);
return internals->pipes[0];
}
-
+#undef vlc_object_kill
/**
* Requests termination of an object, cancels the object thread, and make the
* object wait pipe (if it exists) readable. Not a cancellation point.
*/
-void __vlc_object_kill( vlc_object_t *p_this )
+void vlc_object_kill( vlc_object_t *p_this )
{
vlc_object_internals_t *priv = vlc_internals( p_this );
int fd = -1;
}
}
-
-/*****************************************************************************
- * 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( vlc_internals (p_this)->i_object_type == i_type )
- {
- vlc_object_hold( p_this );
- return p_this;
- }
-
- /* Otherwise, recursively look for the object */
- if (i_mode == FIND_ANYWHERE)
- return vlc_object_find (p_this->p_libvlc, i_type, FIND_CHILD);
-
- switch (i_type)
- {
- case VLC_OBJECT_VOUT:
- case VLC_OBJECT_AOUT:
- break;
- case VLC_OBJECT_INPUT:
- /* input can only be accessed like this from children,
- * otherwise we could not promise that it is initialized */
- if (i_mode != FIND_PARENT)
- return NULL;
- break;
- default:
- return NULL;
- }
-
- libvlc_lock (p_this->p_libvlc);
- switch (i_mode)
- {
- case FIND_PARENT:
- p_found = FindParent (p_this, i_type);
- break;
- case FIND_CHILD:
- p_found = FindChild (vlc_internals (p_this), i_type);
- break;
- default:
- assert (0);
- }
- libvlc_unlock (p_this->p_libvlc);
- return p_found;
-}
-
-
static int objnamecmp(const vlc_object_t *obj, const char *name)
{
char *objname = vlc_object_get_name(obj);
return p_found;
}
+#undef vlc_object_hold
/**
* Increment an object reference counter.
*/
-void * __vlc_object_hold( vlc_object_t *p_this )
+void * vlc_object_hold( vlc_object_t *p_this )
{
vlc_object_internals_t *internals = vlc_internals( p_this );
return p_this;
}
+#undef vlc_object_release
/*****************************************************************************
* Decrement an object refcount
* And destroy the object if its refcount reach zero.
*****************************************************************************/
-void __vlc_object_release( vlc_object_t *p_this )
+void vlc_object_release( vlc_object_t *p_this )
{
vlc_object_internals_t *internals = vlc_internals( p_this );
vlc_object_t *parent = NULL;
if( b_should_destroy )
{
+ /* Detach from parent to protect against FIND_CHILDREN */
parent = p_this->p_parent;
- if (parent)
- /* Detach from parent to protect against FIND_CHILDREN */
- vlc_object_detach_unlocked (p_this);
+ if (likely(parent))
+ {
+ /* Unlink */
+ if (internals->prev != NULL)
+ internals->prev->next = internals->next;
+ else
+ vlc_internals(parent)->first = internals->next;
+ if (internals->next != NULL)
+ internals->next->prev = internals->prev;
+ }
/* We have no children */
assert (internals->first == NULL);
}
}
+#undef vlc_object_attach
/**
****************************************************************************
* attach object to a parent object
*****************************************************************************
* This function sets p_this as a child of p_parent, and p_parent as a parent
- * of p_this. This link can be undone using vlc_object_detach.
+ * of p_this.
*****************************************************************************/
-void __vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent )
+void vlc_object_attach( vlc_object_t *p_this, vlc_object_t *p_parent )
{
if( !p_this ) return;
vlc_object_internals_t *pap = vlc_internals (p_parent);
vlc_object_internals_t *priv = vlc_internals (p_this);
- vlc_object_t *p_old_parent;
priv->prev = NULL;
vlc_object_hold (p_parent);
libvlc_lock (p_this->p_libvlc);
-#ifndef NDEBUG
- /* Reparenting an object carries a risk of invalid access to the parent,
- * from another thread. This can happen when inheriting a variable, or
- * through any direct access to vlc_object_t.p_parent. Also, reparenting
- * brings a functional bug, whereby the reparented object uses incorrect
- * old values for inherited variables (as the new parent may have different
- * variable values, especially if it is an input).
- * Note that the old parent may be already destroyed.
- * So its pointer must not be dereferenced.
- */
- if (priv->old_parent)
- msg_Info (p_this, "Reparenting an object is dangerous (%p -> %p)!",
- priv->old_parent, p_parent);
-#endif
-
- p_old_parent = p_this->p_parent;
- if (p_old_parent)
- vlc_object_detach_unlocked (p_this);
/* Attach the parent to its child */
+ assert (p_this->p_parent == NULL);
p_this->p_parent = p_parent;
/* Attach the child to its parent */
priv->next->prev = priv;
pap->first = priv;
libvlc_unlock (p_this->p_libvlc);
-
- if (p_old_parent)
- vlc_object_release (p_old_parent);
-}
-
-
-static void vlc_object_detach_unlocked (vlc_object_t *p_this)
-{
- assert (p_this->p_parent != NULL);
-
- vlc_object_internals_t *pap = vlc_internals (p_this->p_parent);
- vlc_object_internals_t *priv = vlc_internals (p_this);
-
- /* Unlink */
- if (priv->prev != NULL)
- priv->prev->next = priv->next;
- else
- pap->first = priv->next;
- if (priv->next != NULL)
- priv->next->prev = priv->prev;
-
- /* Remove p_this's parent */
-#ifndef NDEBUG
- priv->old_parent = p_this->p_parent;
-#endif
- p_this->p_parent = NULL;
}
-#undef vlc_object_detach
-/**
- ****************************************************************************
- * detach object from its parent
- *****************************************************************************
- * This function removes all links between an object and its parent.
- *****************************************************************************/
-void vlc_object_detach( vlc_object_t *p_this )
-{
- vlc_object_t *p_parent;
- if( !p_this ) return;
-
- libvlc_lock (p_this->p_libvlc);
- p_parent = p_this->p_parent;
- if (p_parent)
- vlc_object_detach_unlocked( p_this );
- libvlc_unlock (p_this->p_libvlc);
-
- if (p_parent)
- vlc_object_release (p_parent);
-}
+#undef vlc_list_children
/**
* Gets the list of children of an objects, and increment their reference
* count.
* @return a list (possibly empty) or NULL in case of error.
*/
-vlc_list_t *__vlc_list_children( vlc_object_t *obj )
+vlc_list_t *vlc_list_children( vlc_object_t *obj )
{
vlc_list_t *l;
vlc_object_internals_t *priv;
MYCASE( INTEGER, "integer" );
MYCASE( HOTKEY, "hotkey" );
MYCASE( STRING, "string" );
- MYCASE( MODULE, "module" );
- MYCASE( FILE, "file" );
- MYCASE( DIRECTORY, "directory" );
MYCASE( VARIABLE, "variable" );
MYCASE( FLOAT, "float" );
MYCASE( TIME, "time" );
+ MYCASE( COORDS, "coords" );
MYCASE( ADDRESS, "address" );
MYCASE( MUTEX, "mutex" );
- MYCASE( LIST, "list" );
#undef MYCASE
}
printf( " *-o \"%s\" (%s", p_var->psz_name, psz_type );
printf( ": %s", p_var->val.b_bool ? "true" : "false" );
break;
case VLC_VAR_INTEGER:
- printf( ": %d", p_var->val.i_int );
+ printf( ": %"PRId64, p_var->val.i_int );
break;
case VLC_VAR_STRING:
printf( ": \"%s\"", p_var->val.psz_string );
case VLC_VAR_TIME:
printf( ": %"PRIi64, (int64_t)p_var->val.i_time );
break;
+ case VLC_VAR_COORDS:
+ printf( ": %"PRId32"x%"PRId32,
+ p_var->val.coords.x, p_var->val.coords.y );
+ break;
case VLC_VAR_ADDRESS:
printf( ": %p", p_var->val.p_address );
break;
- case VLC_VAR_LIST:
- fputs( ": TODO", stdout );
- break;
}
fputc( '\n', stdout );
}
/* Following functions are local */
-static vlc_object_t *FindParent (vlc_object_t *p_this, int i_type)
-{
- for (vlc_object_t *parent = p_this->p_parent;
- parent != NULL;
- parent = parent->p_parent)
- {
- if (vlc_internals (parent)->i_object_type == i_type)
- return vlc_object_hold (parent);
- }
- return NULL;
-}
-
static vlc_object_t *FindParentName (vlc_object_t *p_this, const char *name)
{
for (vlc_object_t *parent = p_this->p_parent;
return NULL;
}
-static vlc_object_t *FindChild (vlc_object_internals_t *priv, int i_type)
-{
- for (priv = priv->first; priv != NULL; priv = priv->next)
- {
- if (priv->i_object_type == i_type)
- return vlc_object_hold (vlc_externals (priv));
-
- vlc_object_t *found = FindChild (priv, i_type);
- if (found != NULL)
- return found;
- }
- return NULL;
-}
-
static vlc_object_t *FindChildName (vlc_object_internals_t *priv,
const char *name)
{