[vlc-commits] commit: libvlc_Quit: support using a callback ( Rémi Denis-Courmont )

git at videolan.org git at videolan.org
Sun May 30 19:52:34 CEST 2010


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sun May 30 20:17:27 2010 +0300| [6197b056e6f9bd026012db6f1512bbd981e27442] | committer: Rémi Denis-Courmont 

libvlc_Quit: support using a callback

This is more flexible than the current libvlc_InternalWait() which
requires a thread that does nothing for the whole lifetime of VLC.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=6197b056e6f9bd026012db6f1512bbd981e27442
---

 src/Makefile.am               |    1 +
 src/control/libvlc_internal.h |    1 +
 src/interface/interface.c     |    2 -
 src/libvlc.c                  |   36 +-------------
 src/libvlc.h                  |   17 ++++++
 src/libvlccore.sym            |    1 +
 src/misc/exit.c               |  110 +++++++++++++++++++++++++++++++++++++++++
 7 files changed, 132 insertions(+), 36 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index 5ce3214..8a23506 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -428,6 +428,7 @@ SOURCES_libvlc_common = \
 	misc/cpu.c \
 	misc/action.c \
 	misc/epg.c \
+	misc/exit.c \
 	config/configuration.h \
 	config/core.c \
 	config/chain.c \
diff --git a/src/control/libvlc_internal.h b/src/control/libvlc_internal.h
index 7ab347d..c079f8d 100644
--- a/src/control/libvlc_internal.h
+++ b/src/control/libvlc_internal.h
@@ -50,6 +50,7 @@ VLC_EXPORT (void, libvlc_InternalDestroy, ( libvlc_int_t * ) );
 
 VLC_EXPORT (int, libvlc_InternalAddIntf, ( libvlc_int_t *, const char * ) );
 VLC_EXPORT (void, libvlc_InternalWait, ( libvlc_int_t * ) );
+VLC_EXPORT (void, libvlc_SetExitHandler, ( libvlc_int_t *, void (*) (void *), void * ) );
 
 typedef void (*libvlc_vlm_release_func_t)( libvlc_instance_t * ) ;
 
diff --git a/src/interface/interface.c b/src/interface/interface.c
index ba9240b..9268391 100644
--- a/src/interface/interface.c
+++ b/src/interface/interface.c
@@ -182,8 +182,6 @@ void intf_DestroyAll( libvlc_int_t *p_libvlc )
 {
     intf_thread_t *p_first;
 
-    assert( !vlc_object_alive( p_libvlc ) );
-
     vlc_mutex_lock( &lock );
     p_first = libvlc_priv( p_libvlc )->p_intf;
 #ifndef NDEBUG
diff --git a/src/libvlc.c b/src/libvlc.c
index 3d78cde..9affe8c 100644
--- a/src/libvlc.c
+++ b/src/libvlc.c
@@ -273,6 +273,7 @@ libvlc_int_t * libvlc_InternalCreate( void )
 
     /* Initialize mutexes */
     vlc_mutex_init( &priv->timer_lock );
+    vlc_ExitInit( &priv->exit );
 
     return p_libvlc;
 error:
@@ -1073,6 +1074,7 @@ void libvlc_InternalDestroy( libvlc_int_t *p_libvlc )
     msg_Destroy (priv->msg_bank);
 
     /* Destroy mutexes */
+    vlc_ExitDestroy( &priv->exit );
     vlc_mutex_destroy( &priv->timer_lock );
 
 #ifndef NDEBUG /* Hack to dump leaked objects tree */
@@ -1121,40 +1123,6 @@ int libvlc_InternalAddIntf( libvlc_int_t *p_libvlc, char const *psz_module )
     return ret;
 }
 
-#ifndef WIN32
-static vlc_mutex_t exit_lock = VLC_STATIC_MUTEX;
-static vlc_cond_t  exiting = VLC_STATIC_COND;
-#else
-extern vlc_mutex_t super_mutex;
-extern vlc_cond_t  super_variable;
-# define exit_lock super_mutex
-# define exiting   super_variable
-#endif
-
-/**
- * Waits until the LibVLC instance gets an exit signal. Normally, this happens
- * when the user "exits" an interface plugin.
- */
-void libvlc_InternalWait( libvlc_int_t *p_libvlc )
-{
-    vlc_mutex_lock( &exit_lock );
-    while( vlc_object_alive( p_libvlc ) )
-        vlc_cond_wait( &exiting, &exit_lock );
-    vlc_mutex_unlock( &exit_lock );
-}
-
-/**
- * Posts an exit signal to LibVLC instance. This will normally initiate the
- * cleanup and destroy process. It should only be called on behalf of the user.
- */
-void libvlc_Quit( libvlc_int_t *p_libvlc )
-{
-    vlc_mutex_lock( &exit_lock );
-    vlc_object_kill( p_libvlc );
-    vlc_cond_broadcast( &exiting );
-    vlc_mutex_unlock( &exit_lock );
-}
-
 #if defined( ENABLE_NLS ) && (defined (__APPLE__) || defined (WIN32)) && \
     ( defined( HAVE_GETTEXT ) || defined( HAVE_INCLUDED_GETTEXT ) )
 /*****************************************************************************
diff --git a/src/libvlc.h b/src/libvlc.h
index a9fd3d1..873b73c 100644
--- a/src/libvlc.h
+++ b/src/libvlc.h
@@ -94,6 +94,20 @@ const char* msg_StackMsg ( void );
 char *vlc_fix_readdir (const char *);
 
 /*
+ * LibVLC exit event handling
+ */
+typedef struct vlc_exit
+{
+    vlc_mutex_t lock;
+    void (*handler) (void *);
+    void *opaque;
+    bool killed;
+} vlc_exit_t;
+
+void vlc_ExitInit( vlc_exit_t * );
+void vlc_ExitDestroy( vlc_exit_t * );
+
+/*
  * LibVLC objects stuff
  */
 
@@ -210,6 +224,9 @@ typedef struct libvlc_priv_t
 
     /* Objects tree */
     vlc_mutex_t        structure_lock;
+
+    /* Exit callback */
+    vlc_exit_t       exit;
 } libvlc_priv_t;
 
 static inline libvlc_priv_t *libvlc_priv (libvlc_int_t *libvlc)
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 6767a6b..d8cd222 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -234,6 +234,7 @@ libvlc_InternalDestroy
 libvlc_InternalInit
 libvlc_InternalWait
 libvlc_Quit
+libvlc_SetExitHandler
 LocaleFree
 make_URI
 make_path
diff --git a/src/misc/exit.c b/src/misc/exit.c
new file mode 100644
index 0000000..65c3809
--- /dev/null
+++ b/src/misc/exit.c
@@ -0,0 +1,110 @@
+/*****************************************************************************
+ * quit.c: LibVLC termination event
+ *****************************************************************************
+ * Copyright (C) 2009-2010 the VideoLAN team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_interface.h>
+#include "libvlc.h"
+#include "control/libvlc_internal.h"
+
+void vlc_ExitInit( vlc_exit_t *exit )
+{
+    vlc_mutex_init( &exit->lock );
+    exit->handler = NULL;
+    exit->opaque = NULL;
+    exit->killed = false;
+}
+
+void vlc_ExitDestroy( vlc_exit_t *exit )
+{
+    vlc_mutex_destroy( &exit->lock );
+}
+
+
+/**
+ * Registers a callback for the LibVLC exit event.
+ *
+ * @note This function conflicts with libvlc_InternalWait().
+ * Use either or none of them, but not both.
+ */
+void libvlc_SetExitHandler( libvlc_int_t *p_libvlc, void (*handler) (void *),
+                            void *opaque )
+{
+    vlc_exit_t *exit = &libvlc_priv( p_libvlc )->exit;
+
+    vlc_mutex_lock( &exit->lock );
+    if( exit->killed ) /* already exited! (race condition) */
+        handler( opaque );
+    exit->handler = handler;
+    exit->opaque = opaque;
+    vlc_mutex_unlock( &exit->lock );
+}
+
+/**
+ * Posts an exit signal to LibVLC instance. This only emits a notification to
+ * the main thread. It might take a while before the actual cleanup occurs.
+ * This function should only be called on behalf of the user.
+ */
+void libvlc_Quit( libvlc_int_t *p_libvlc )
+{
+    vlc_exit_t *exit = &libvlc_priv( p_libvlc )->exit;
+
+    vlc_mutex_lock( &exit->lock );
+    if( !exit->killed )
+    {
+        msg_Dbg( p_libvlc, "exiting" );
+        exit->killed = true;
+        if( exit->handler != NULL )
+            exit->handler( exit->opaque );
+    }
+    vlc_mutex_unlock( &exit->lock );
+}
+
+
+static void exit_wakeup( void *data )
+{
+    vlc_cond_signal( data );
+}
+
+/**
+ * Waits until the LibVLC instance gets an exit signal.
+ * This normally occurs when the user "exits" an interface plugin. But it can
+ * also be triggered by the special vlc://quit item, the update checker, or
+ * the playlist engine.
+ */
+void libvlc_InternalWait( libvlc_int_t *p_libvlc )
+{
+    vlc_exit_t *exit = &libvlc_priv( p_libvlc )->exit;
+    vlc_cond_t wait;
+
+    vlc_cond_init( &wait );
+
+    vlc_mutex_lock( &exit->lock );
+    exit->handler = exit_wakeup;
+    exit->opaque = &wait;
+    while( !exit->killed )
+        vlc_cond_wait( &wait, &exit->lock );
+    vlc_mutex_unlock( &exit->lock );
+
+    vlc_cond_destroy( &wait );
+}



More information about the vlc-commits mailing list