[vlc-commits] playlist: merge interface and playlist locks as one
Rémi Denis-Courmont
git at videolan.org
Tue Jan 7 23:07:58 CET 2014
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Mon Jan 6 10:32:07 2014 +0200| [a5056a2d8fb05af732914c37e6bd15f56a97aa9d] | committer: Rémi Denis-Courmont
playlist: merge interface and playlist locks as one
This restores symmetry in the playlist API, but most importantly, it
is necessary to fix some corner case races (in later commits).
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=a5056a2d8fb05af732914c37e6bd15f56a97aa9d
---
src/interface/interface.c | 43 ++++++++++++++++++++++++++++++++++----
src/libvlc.c | 4 ++--
src/libvlc.h | 2 +-
src/playlist/engine.c | 22 +------------------
src/playlist/playlist_internal.h | 1 +
5 files changed, 44 insertions(+), 28 deletions(-)
diff --git a/src/interface/interface.c b/src/interface/interface.c
index b059956..b24cd69 100644
--- a/src/interface/interface.c
+++ b/src/interface/interface.c
@@ -43,15 +43,22 @@
#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
diff --git a/src/libvlc.c b/src/libvlc.c
index 7dbda91..d6c63ad 100644
--- a/src/libvlc.c
+++ b/src/libvlc.c
@@ -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 );
diff --git a/src/libvlc.h b/src/libvlc.h
index a9c49da..d32976a 100644
--- a/src/libvlc.h
+++ b/src/libvlc.h
@@ -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
diff --git a/src/playlist/engine.c b/src/playlist/engine.c
index 4861602..d9af6f0 100644
--- a/src/playlist/engine.c
+++ b/src/playlist/engine.c
@@ -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 )
diff --git a/src/playlist/playlist_internal.h b/src/playlist/playlist_internal.h
index 628fc56..2fbaaac 100644
--- a/src/playlist/playlist_internal.h
+++ b/src/playlist/playlist_internal.h
@@ -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 * );
More information about the vlc-commits
mailing list