]> git.sesse.net Git - vlc/blobdiff - src/libvlc.c
GC: thread-safety, and offset independence
[vlc] / src / libvlc.c
index a56443063fd5a7e17cbdd270b3ec2f16145f4001..87920fb96a02f1cafa7ab843848bccd8c57548c9 100644 (file)
 #include "audio_output/aout_internal.h"
 
 #include <vlc_vout.h>
-
 #include <vlc_sout.h>
-#include "stream_output/stream_output.h"
-
 #include <vlc_charset.h>
 
 #include "libvlc.h"
@@ -107,39 +104,63 @@ static unsigned          i_instances = 0;
 static bool b_daemon = false;
 #endif
 
-/*****************************************************************************
- * vlc_gc_*.
- *****************************************************************************/
-void __vlc_gc_incref( gc_object_t * p_gc )
-{
-    assert( p_gc->i_gc_refcount > 0 );
+#undef vlc_gc_init
+#undef vlc_hold
+#undef vlc_release
 
-    /* FIXME: atomic version needed! */
-    p_gc->i_gc_refcount ++;
+/**
+ * Atomically set the reference count to 1.
+ * @param p_gc reference counted object
+ * @param pf_destruct destruction calback
+ * @return p_gc.
+ */
+void *vlc_gc_init (gc_object_t *p_gc, void (*pf_destruct) (gc_object_t *))
+{
+    p_gc->pf_destructor = pf_destruct;
+
+    /* Nobody else can possibly lock the spin - it's there as a barrier */
+    vlc_spin_init (&p_gc->spin);
+    vlc_spin_lock (&p_gc->spin);
+    p_gc->refs = 1;
+    vlc_spin_unlock (&p_gc->spin);
+    return p_gc;
 }
 
-void __vlc_gc_decref( gc_object_t *p_gc )
+/**
+ * Atomically increment the reference count.
+ * @param p_gc reference counted object
+ * @return p_gc.
+ */
+void *vlc_hold (gc_object_t * p_gc)
 {
     assert( p_gc );
-    assert( p_gc->i_gc_refcount > 0 );
 
-    /* FIXME: atomic version needed! */
-    p_gc->i_gc_refcount -- ;
-
-    if( p_gc->i_gc_refcount == 0 )
-    {
-        p_gc->pf_destructor( p_gc );
-        /* Do not use the p_gc pointer from now on ! */
-    }
+    vlc_spin_lock (&p_gc->spin);
+    assert (p_gc->refs > 0);
+    p_gc->refs++;
+    vlc_spin_unlock (&p_gc->spin);
+    return p_gc;
 }
 
-void
-__vlc_gc_init( gc_object_t * p_gc, void (*pf_destructor)( gc_object_t * ),
-               void * arg)
+/**
+ * Atomically decrement the reference count and, if it reaches zero, destroy.
+ * @param p_gc reference counted object.
+ */
+void vlc_release (gc_object_t *p_gc)
 {
-    p_gc->i_gc_refcount = 1;
-    p_gc->pf_destructor = pf_destructor;
-    p_gc->p_destructor_arg = arg;
+    bool dead;
+
+    assert( p_gc );
+    vlc_spin_lock (&p_gc->spin);
+    assert (p_gc->refs > 0);
+    dead = !--p_gc->refs;
+    vlc_spin_unlock (&p_gc->spin);
+
+    if (dead)
+    {
+        vlc_spin_destroy (&p_gc->spin);
+        p_gc->pf_destructor (p_gc);
+    }
 }
 
 /*****************************************************************************
@@ -207,6 +228,7 @@ libvlc_int_t * libvlc_InternalCreate( void )
     priv->p_playlist = NULL;
     priv->p_interaction = NULL;
     priv->p_vlm = NULL;
+    p_libvlc->psz_object_name = strdup( "libvlc" );
 
     /* Initialize message queue */
     msg_Create( p_libvlc );
@@ -533,7 +555,9 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
 #ifdef HAVE_DBUS
     dbus_threads_init_default();
 
-    if( config_GetInt( p_libvlc, "one-instance" ) > 0 )
+    if( config_GetInt( p_libvlc, "one-instance" ) > 0
+        || ( config_GetInt( p_libvlc, "one-instance-when-started-from-file" )
+             && config_GetInt( p_libvlc, "started-from-file" ) ) )
     {
         /* Initialise D-Bus interface, check for other instances */
         DBusConnection  *p_conn = NULL;
@@ -853,7 +877,9 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int i_argc,
 #ifdef HAVE_DBUS
     /* loads dbus control interface if in one-instance mode
      * we do it only when playlist exists, because dbus module needs it */
-    if( config_GetInt( p_libvlc, "one-instance" ) > 0 )
+    if( config_GetInt( p_libvlc, "one-instance" ) > 0
+        || ( config_GetInt( p_libvlc, "one-instance-when-started-from-file" )
+             && config_GetInt( p_libvlc, "started-from-file" ) ) )
         libvlc_InternalAddIntf( p_libvlc, "dbus,none" );
 
     /* Prevents the power management daemon from suspending the system
@@ -1021,24 +1047,10 @@ int libvlc_InternalCleanup( libvlc_int_t *p_libvlc )
     stats_TimersDumpAll( p_libvlc );
     stats_TimersCleanAll( p_libvlc );
 
-#ifdef ENABLE_SOUT
-    announce_handler_t * p_announce;
-
-    /* Free announce handler(s?) */
-    while( (p_announce = vlc_object_find( p_libvlc, VLC_OBJECT_ANNOUNCE,
-                                                 FIND_CHILD ) ) )
-    {
-        msg_Dbg( p_libvlc, "removing announce handler" );
-        vlc_object_detach( p_announce );
-        vlc_object_release( p_announce );
-        announce_HandlerDestroy( p_announce );
-    }
-#endif
-
     bool b_clean = true;
     FOREACH_ARRAY( input_item_t *p_del, priv->input_items )
-        msg_Err( p_libvlc, "input item %p has not been deleted properly: refcount %d, name %s",
-            p_del, p_del->i_gc_refcount, p_del->psz_name ? p_del->psz_name : "(null)" );
+        msg_Err( p_libvlc, "input item %p has not been deleted properly: name %s",
+            p_del, p_del->psz_name ? p_del->psz_name : "(null)" );
         b_clean = false;
     FOREACH_END();
     assert( b_clean );