#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"
#include <vlc_vlm.h>
+#ifdef __APPLE__
+# include <libkern/OSAtomic.h>
+#endif
+
#include <assert.h>
/*****************************************************************************
static bool b_daemon = false;
#endif
-/*****************************************************************************
- * vlc_gc_*.
- *****************************************************************************/
-void __vlc_gc_incref( gc_object_t * p_gc )
+#undef vlc_gc_init
+#undef vlc_hold
+#undef vlc_release
+
+/**
+ * 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 *))
{
- assert( p_gc->i_gc_refcount > 0 );
+ /* There is no point in using the GC if there is no destructor... */
+ assert (pf_destruct);
+ p_gc->pf_destructor = pf_destruct;
+
+ p_gc->refs = 1;
+#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
+ __sync_synchronize ();
+#elif defined (WIN32) && defined (__GNUC__)
+#elif defined(__APPLE__)
+ OSMemoryBarrier ();
+#else
+ /* 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);
+ vlc_spin_unlock (&p_gc->spin);
+#endif
+ return p_gc;
+}
+
+/**
+ * Atomically increment the reference count.
+ * @param p_gc reference counted object
+ * @return p_gc.
+ */
+void *vlc_hold (gc_object_t * p_gc)
+{
+ uintptr_t refs;
+ assert( p_gc );
- /* FIXME: atomic version needed! */
- p_gc->i_gc_refcount ++;
+#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
+ refs = __sync_add_and_fetch (&p_gc->refs, 1);
+#elif defined (WIN32) && defined (__GNUC__)
+ refs = __builtin_choose_expr (sizeof (uintptr_t) == 4,
+ InterlockedIncrement (&p_gc->refs),
+ InterlockedIncrement64 (&p_gc->refs));
+#elif defined(__APPLE__)
+ refs = OSAtomicIncrement32Barrier((int*)&p_gc->refs);
+#else
+ vlc_spin_lock (&p_gc->spin);
+ refs = ++p_gc->refs;
+ vlc_spin_unlock (&p_gc->spin);
+#endif
+ assert (refs != 1); /* there had to be a reference already */
+ return p_gc;
}
-void __vlc_gc_decref( gc_object_t *p_gc )
+/**
+ * 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)
{
+ unsigned refs;
+
assert( p_gc );
- assert( p_gc->i_gc_refcount > 0 );
- /* FIXME: atomic version needed! */
- p_gc->i_gc_refcount -- ;
+#if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
+ refs = __sync_sub_and_fetch (&p_gc->refs, 1);
+#elif defined (WIN32) && defined (__GNUC__)
+ refs = __builtin_choose_expr (sizeof (uintptr_t) == 4,
+ InterlockedDecrement (&p_gc->refs),
+ InterlockedDecrement64 (&p_gc->refs));
+#elif defined(__APPLE__)
+ refs = OSAtomicDecrement32Barrier((int*)&p_gc->refs);
+#else
+ vlc_spin_lock (&p_gc->spin);
+ refs = --p_gc->refs;
+ vlc_spin_unlock (&p_gc->spin);
+#endif
- if( p_gc->i_gc_refcount == 0 )
+ assert (refs != (uintptr_t)(-1)); /* reference underflow?! */
+ if (refs == 0)
{
- p_gc->pf_destructor( p_gc );
- /* Do not use the p_gc pointer from now on ! */
+#ifdef USE_SYNC
+#elif defined (WIN32) && defined (__GNUC__)
+#elif defined(__APPLE__)
+#else
+ vlc_spin_destroy (&p_gc->spin);
+#endif
+ p_gc->pf_destructor (p_gc);
}
}
-void
-__vlc_gc_init( gc_object_t * p_gc, void (*pf_destructor)( gc_object_t * ),
- void * arg)
-{
- p_gc->i_gc_refcount = 1;
- p_gc->pf_destructor = pf_destructor;
- p_gc->p_destructor_arg = arg;
-}
-
/*****************************************************************************
* Local prototypes
*****************************************************************************/
b_exit = true;
}
- msg_Dbg( p_libvlc, "module bank initialized, found %i modules",
- vlc_internals( p_module_bank )->i_children );
+ size_t module_count;
+ module_t **list = module_list_get( &module_count );
+ module_list_free( list );
+ msg_Dbg( p_libvlc, "module bank initialized (%u modules)", module_count );
/* Check for help on modules */
if( (p_tmp = config_GetPsz( p_libvlc, "module" )) )
/*
* Choose the best memcpy module
*/
- priv->p_memcpy_module = module_Need( p_libvlc, "memcpy", "$memcpy", 0 );
+ priv->p_memcpy_module = module_need( p_libvlc, "memcpy", "$memcpy", 0 );
priv->b_stats = config_GetInt( p_libvlc, "stats" ) > 0;
priv->i_timers = 0;
vlc_mutex_init( &p_libvlc->p_stats->lock );
priv->p_stats_computer = NULL;
- /* Init the array that holds every input item */
- ARRAY_INIT( priv->input_items );
- priv->i_last_input_id = 0;
+ priv->i_last_input_id = 0; /* Not very safe, should be removed */
/*
* Initialize hotkey handling
msg_Err( p_libvlc, "playlist initialization failed" );
if( priv->p_memcpy_module != NULL )
{
- module_Unneed( p_libvlc, priv->p_memcpy_module );
+ module_unneed( p_libvlc, priv->p_memcpy_module );
}
module_EndBank( p_libvlc );
return VLC_EGENERIC;
var_Get( p_libvlc, "open", &val );
if ( val.psz_string != NULL && *val.psz_string )
{
- playlist_t *p_playlist = pl_Yield( p_libvlc );
+ playlist_t *p_playlist = pl_Hold( p_libvlc );
playlist_AddExt( p_playlist, val.psz_string, NULL, PLAYLIST_INSERT, 0,
-1, NULL, 0, true, pl_Unlocked );
pl_Release( p_libvlc );
playlist_ServicesDiscoveryKillAll( p_playlist );
/* Free playlist */
- /* Any thread still running must not assume pl_Yield() succeeds. */
+ /* Any thread still running must not assume pl_Hold() succeeds. */
msg_Dbg( p_libvlc, "removing playlist" );
priv->p_playlist = NULL;
- vlc_object_kill( p_playlist ); /* <-- memory barrier for pl_Yield() */
+ vlc_object_kill( p_playlist ); /* <-- memory barrier for pl_Hold() */
vlc_thread_join( p_playlist );
vlc_object_release( p_playlist );
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)" );
- b_clean = false;
- FOREACH_END();
- assert( b_clean );
- ARRAY_RESET( priv->input_items );
-
msg_Dbg( p_libvlc, "removing stats" );
vlc_mutex_destroy( &p_libvlc->p_stats->lock );
FREENULL( p_libvlc->p_stats );
if( priv->p_memcpy_module )
{
- module_Unneed( p_libvlc, priv->p_memcpy_module );
+ module_unneed( p_libvlc, priv->p_memcpy_module );
priv->p_memcpy_module = NULL;
}
/* TODO: write an internal function of this one, to avoid
* unnecessary lookups. */
- playlist_t *p_playlist = pl_Yield( p_vlc );
+ playlist_t *p_playlist = pl_Hold( p_vlc );
playlist_AddExt( p_playlist, ppsz_argv[i_opt], NULL, PLAYLIST_INSERT,
0, -1, ( i_options ? &ppsz_argv[i_opt + 1] : NULL ),
i_options, true, pl_Unlocked );
#else
# define OPTION_VALUE_SEP " "
#endif
- vlc_list_t *p_list = NULL;
char psz_spaces_text[PADDING_SPACES+LINE_START+1];
char psz_spaces_longtext[LINE_START+3];
char psz_format[sizeof(COLOR_FORMAT_STRING)];
char psz_format_bool[sizeof(COLOR_FORMAT_STRING_BOOL)];
char psz_buffer[10000];
char psz_short[4];
- int i_index;
int i_width = ConsoleWidth() - (PADDING_SPACES+LINE_START+1);
int i_width_description = i_width + PADDING_SPACES - 1;
bool b_advanced = config_GetInt( p_this, "advanced" ) > 0;
}
/* List all modules */
- p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
+ module_t **list = module_list_get (NULL);
+ if (!list)
+ return;
/* Ugly hack to make sure that the help options always come first
* (part 1) */
Usage( p_this, "help" );
/* Enumerate the config for each module */
- for( i_index = 0; i_index < p_list->i_count; i_index++ )
+ for (size_t i = 0; list[i]; i++)
{
bool b_help_module;
- module_t *p_parser = (module_t *)p_list->p_values[i_index].p_object;
+ module_t *p_parser = list[i];
module_config_t *p_item = NULL;
module_config_t *p_section = NULL;
module_config_t *p_end = p_parser->p_config + p_parser->confsize;
}
/* Release the module list */
- vlc_list_release( p_list );
+ module_list_free (list);
}
/*****************************************************************************
*****************************************************************************/
static void ListModules( libvlc_int_t *p_this, bool b_verbose )
{
- vlc_list_t *p_list = NULL;
- module_t *p_parser = NULL;
+ module_t *p_parser;
char psz_spaces[22];
- int i_index;
bool b_color = config_GetInt( p_this, "color" ) > 0;
#endif
/* List all modules */
- p_list = vlc_list_find( p_this, VLC_OBJECT_MODULE, FIND_ANYWHERE );
+ module_t **list = module_list_get (NULL);
/* Enumerate each module */
- for( i_index = 0; i_index < p_list->i_count; i_index++ )
+ for (size_t j = 0; (p_parser = list[j]) != NULL; j++)
{
int i;
- p_parser = (module_t *)p_list->p_values[i_index].p_object ;
-
/* Nasty hack, but right now I'm too tired to think about a nice
* solution */
i = 22 - strlen( p_parser->psz_object_name ) - 1;
psz_spaces[i] = ' ';
}
-
- vlc_list_release( p_list );
+ module_list_free (list);
#ifdef WIN32 /* Pause the console because it's destroyed when we exit */
PauseConsole();