]> git.sesse.net Git - vlc/commitdiff
playlist: merge interface and playlist locks as one
authorRémi Denis-Courmont <remi@remlab.net>
Mon, 6 Jan 2014 08:32:07 +0000 (10:32 +0200)
committerRémi Denis-Courmont <remi@remlab.net>
Tue, 7 Jan 2014 22:07:50 +0000 (00:07 +0200)
This restores symmetry in the playlist API, but most importantly, it
is necessary to fix some corner case races (in later commits).

src/interface/interface.c
src/libvlc.c
src/libvlc.h
src/playlist/engine.c
src/playlist/playlist_internal.h

index b0599562aebfa1e3ae1d01e614afe6ef4ff4ffb6..b24cd697ffb97f839eaab3686624f0369c2248cd 100644 (file)
 #include <vlc_common.h>
 #include <vlc_modules.h>
 #include <vlc_interface.h>
+#include <vlc_playlist.h>
 #include "libvlc.h"
-
-#ifdef __APPLE__
-#include "../lib/libvlc_internal.h"
-#endif
+#include "playlist/playlist_internal.h"
 
 static int AddIntfCallback( vlc_object_t *, char const *,
                             vlc_value_t , vlc_value_t , void * );
 
+/* This lock ensures that the playlist is created only once (per instance). It
+ * also protects the list of running interfaces against concurrent access,
+ * either to add or remove an interface.
+ *
+ * However, it does NOT protect from destruction of the playlist by
+ * intf_DestroyAll(). Instead, care must be taken that intf_Create() and any
+ * other function that depends on the playlist is only called BEFORE
+ * intf_DestroyAll() has the possibility to destroy all interfaces.
+ */
 static vlc_mutex_t lock = VLC_STATIC_MUTEX;
 
 #undef intf_Create
@@ -129,6 +136,34 @@ error:
     return VLC_EGENERIC;
 }
 
+/**
+ * Creates the playlist if necessary, and return a pointer to it.
+ * @note The playlist is not reference-counted. So the pointer is only valid
+ * until intf_DestroyAll() destroys interfaces.
+ */
+static playlist_t *intf_GetPlaylist(libvlc_int_t *libvlc)
+{
+    playlist_t *playlist;
+
+    vlc_mutex_lock(&lock);
+    playlist = libvlc_priv(libvlc)->playlist;
+    if (playlist == NULL)
+    {
+        playlist = playlist_Create(VLC_OBJECT(libvlc));
+        libvlc_priv(libvlc)->playlist = playlist;
+    }
+    vlc_mutex_unlock(&lock);
+
+    return playlist;
+}
+
+playlist_t *(pl_Get)(vlc_object_t *obj)
+{
+    playlist_t *pl = intf_GetPlaylist(obj->p_libvlc);
+    if (unlikely(pl == NULL))
+        abort();
+    return pl;
+}
 
 /**
  * Stops and destroys all interfaces
index 7dbda91560aa5656b44b6687b4a9c3d06c7d91e4..d6c63ade9e8ea31bb213a80a313647307cc512f9 100644 (file)
@@ -101,7 +101,7 @@ libvlc_int_t * libvlc_InternalCreate( void )
         return NULL;
 
     priv = libvlc_priv (p_libvlc);
-    priv->p_playlist = NULL;
+    priv->playlist = NULL;
     priv->p_dialog_provider = NULL;
     priv->p_vlm = NULL;
 
@@ -536,7 +536,7 @@ void libvlc_InternalCleanup( libvlc_int_t *p_libvlc )
 #endif
 
     /* Free playlist now, all threads are gone */
-    playlist_t *p_playlist = libvlc_priv (p_libvlc)->p_playlist;
+    playlist_t *p_playlist = libvlc_priv (p_libvlc)->playlist;
     if( p_playlist != NULL )
         playlist_Destroy( p_playlist );
 
index a9c49da487b86ed925e7477008c8ebb0dd6ab949..d32976afc81c9686ce24a896af170fcb0af6530a 100644 (file)
@@ -157,12 +157,12 @@ typedef struct libvlc_priv_t
     bool               b_stats;     ///< Whether to collect stats
 
     /* Singleton objects */
-    playlist_t        *p_playlist; ///< the playlist singleton
     vlm_t             *p_vlm;  ///< the VLM singleton (or NULL)
     vlc_object_t      *p_dialog_provider; ///< dialog provider
 #ifdef ENABLE_SOUT
     sap_handler_t     *p_sap; ///< SAP SDP advertiser
 #endif
+    struct playlist_t *playlist; ///< Playlist for interfaces
     struct playlist_preparser_t *parser; ///< Input item meta data handler
     struct vlc_actions *actions; ///< Hotkeys handler
 
index 4861602d836843d2bca1071973f5b46d758fc67b..d9af6f0b71db3cb7fd671c0e41cb4e69c1635d5c 100644 (file)
@@ -195,7 +195,7 @@ static int VideoSplitterCallback( vlc_object_t *p_this, char const *psz_cmd,
  * \param p_parent the vlc object that is to be the parent of this playlist
  * \return a pointer to the created playlist, or NULL on error
  */
-static playlist_t *playlist_Create( vlc_object_t *p_parent )
+playlist_t *playlist_Create( vlc_object_t *p_parent )
 {
     playlist_t *p_playlist;
     playlist_private_t *p;
@@ -374,26 +374,6 @@ void playlist_Destroy( playlist_t *p_playlist )
     vlc_object_release( p_playlist );
 }
 
-#undef pl_Get
-playlist_t *pl_Get (vlc_object_t *obj)
-{
-    static vlc_mutex_t lock = VLC_STATIC_MUTEX;
-    libvlc_int_t *p_libvlc = obj->p_libvlc;
-    playlist_t *pl;
-
-    vlc_mutex_lock (&lock);
-    pl = libvlc_priv (p_libvlc)->p_playlist;
-    if (unlikely(pl == NULL))
-    {
-        pl = playlist_Create (VLC_OBJECT(p_libvlc));
-        if (unlikely(pl == NULL))
-            abort();
-        libvlc_priv (p_libvlc)->p_playlist = pl;
-    }
-    vlc_mutex_unlock (&lock);
-    return pl;
-}
-
 /** Get current playing input.
  */
 input_thread_t * playlist_CurrentInput( playlist_t * p_playlist )
index 628fc5697b243b9b35d74c16a3202136e1a7a8df..2fbaaacdba6765701176086f44d4341e22f4e29f 100644 (file)
@@ -99,6 +99,7 @@ typedef struct playlist_private_t
  *****************************************************************************/
 
 /* Creation/Deletion */
+playlist_t *playlist_Create( vlc_object_t * );
 void playlist_Destroy( playlist_t * );
 void playlist_Activate( playlist_t * );