vlc | branch: master | Rémi Denis-Courmont <r...@remlab.net> | Tue Apr 17 21:35:08 2018 +0300| [c3e4633e1687ec1f0e4a41b99e8eef8797d83abe] | committer: Rémi Denis-Courmont
variables: use linked listed for callbacks > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=c3e4633e1687ec1f0e4a41b99e8eef8797d83abe --- src/misc/variables.c | 144 ++++++++++++++++++++++++++------------------------- 1 file changed, 73 insertions(+), 71 deletions(-) diff --git a/src/misc/variables.c b/src/misc/variables.c index 2426215954..c1ebd64302 100644 --- a/src/misc/variables.c +++ b/src/misc/variables.c @@ -45,6 +45,7 @@ typedef struct callback_entry_t { + struct callback_entry_t *next; union { vlc_callback_t pf_value_callback; @@ -61,12 +62,6 @@ typedef struct variable_ops_t void (*pf_free) ( vlc_value_t * ); } variable_ops_t; -typedef struct callback_table_t -{ - int i_entries; - callback_entry_t * p_entries; -} callback_table_t; - /** * The structure describing a variable. * \note vlc_value_t is the common union for variable values @@ -98,9 +93,9 @@ struct variable_t bool b_incallback; /** Registered value callbacks */ - callback_table_t value_callbacks; + callback_entry_t *value_callbacks; /** Registered list callbacks */ - callback_table_t list_callbacks; + callback_entry_t *list_callbacks; }; static int CmpBool( vlc_value_t v, vlc_value_t w ) @@ -176,7 +171,14 @@ static void Destroy( variable_t *p_var ) free( p_var->psz_name ); free( p_var->psz_text ); - free( p_var->value_callbacks.p_entries ); + while (unlikely(p_var->value_callbacks != NULL)) + { + callback_entry_t *next = p_var->value_callbacks->next; + + free(p_var->value_callbacks); + p_var->value_callbacks = next; + } + assert(p_var->list_callbacks == NULL); free( p_var ); } @@ -237,20 +239,22 @@ static void TriggerCallback(vlc_object_t *obj, variable_t *var, { assert(obj != NULL); - size_t count = var->value_callbacks.i_entries; - if (count == 0) + callback_entry_t *entry = var->value_callbacks; + if (entry == NULL) return; - callback_entry_t *entries = var->value_callbacks.p_entries; vlc_object_internals_t *priv = vlc_internals(obj); assert(!var->b_incallback); var->b_incallback = true; vlc_mutex_unlock(&priv->var_lock); - for (size_t i = 0; i < count; i++) - entries[i].pf_value_callback(obj, name, prev, var->val, - entries[i].p_data); + do + { + entry->pf_value_callback(obj, name, prev, var->val, entry->p_data); + entry = entry->next; + } + while (entry != NULL); vlc_mutex_lock(&priv->var_lock); var->b_incallback = false; @@ -262,20 +266,22 @@ static void TriggerListCallback(vlc_object_t *obj, variable_t *var, { assert(obj != NULL); - size_t count = var->list_callbacks.i_entries; - if (count == 0) + callback_entry_t *entry = var->value_callbacks; + if (entry == NULL) return; - callback_entry_t *entries = var->list_callbacks.p_entries; vlc_object_internals_t *priv = vlc_internals(obj); assert(!var->b_incallback); var->b_incallback = true; vlc_mutex_unlock(&priv->var_lock); - for (size_t i = 0; i < count; i++) - entries[i].pf_list_callback(obj, name, action, val, - entries[i].p_data); + do + { + entry->pf_list_callback(obj, name, action, val, entry->p_data); + entry = entry->next; + } + while (entry != NULL); vlc_mutex_lock(&priv->var_lock); var->b_incallback = false; @@ -303,7 +309,7 @@ int (var_Create)( vlc_object_t *p_this, const char *psz_name, int i_type ) p_var->choices_text.p_values = NULL; p_var->b_incallback = false; - p_var->value_callbacks = (callback_table_t){ 0, NULL }; + p_var->value_callbacks = NULL; /* Always initialize the variable, even if it is a list variable; this * will lead to errors if the variable is not initialized, but it will @@ -759,7 +765,8 @@ typedef enum } vlc_callback_type_t; static void AddCallback( vlc_object_t *p_this, const char *psz_name, - callback_entry_t entry, vlc_callback_type_t i_type ) + callback_entry_t *restrict entry, + vlc_callback_type_t i_type ) { variable_t *p_var; @@ -772,18 +779,21 @@ static void AddCallback( vlc_object_t *p_this, const char *psz_name, { vlc_mutex_unlock( &p_priv->var_lock ); msg_Err( p_this, "cannot add callback %p to nonexistent variable '%s'", - entry.p_callback, psz_name ); + entry->p_callback, psz_name ); return; } WaitUnused( p_this, p_var ); - callback_table_t *p_table; + callback_entry_t **pp; + if (i_type == vlc_value_callback) - p_table = &p_var->value_callbacks; + pp = &p_var->value_callbacks; else - p_table = &p_var->list_callbacks; - TAB_APPEND(p_table->i_entries, p_table->p_entries, entry); + pp = &p_var->list_callbacks; + + entry->next = *pp; + *pp = entry; vlc_mutex_unlock( &p_priv->var_lock ); } @@ -791,21 +801,19 @@ static void AddCallback( vlc_object_t *p_this, const char *psz_name, void (var_AddCallback)(vlc_object_t *p_this, const char *psz_name, vlc_callback_t pf_callback, void *p_data) { - callback_entry_t entry; - entry.pf_value_callback = pf_callback; - entry.p_data = p_data; + callback_entry_t *entry = xmalloc(sizeof (*entry)); + entry->pf_value_callback = pf_callback; + entry->p_data = p_data; AddCallback(p_this, psz_name, entry, vlc_value_callback); } static void DelCallback( vlc_object_t *p_this, const char *psz_name, - callback_entry_t entry, vlc_callback_type_t i_type ) + const callback_entry_t *restrict match, + vlc_callback_type_t i_type ) { - int i_entry; + callback_entry_t **pp, *entry; variable_t *p_var; -#ifndef NDEBUG - bool b_found_similar = false; -#endif assert( p_this ); @@ -816,46 +824,31 @@ static void DelCallback( vlc_object_t *p_this, const char *psz_name, { vlc_mutex_unlock( &p_priv->var_lock ); msg_Err( p_this, "cannot delete callback %p from nonexistent " - "variable '%s'", entry.p_callback, psz_name ); + "variable '%s'", match->p_callback, psz_name ); return; } WaitUnused( p_this, p_var ); - callback_table_t *p_table; if (i_type == vlc_value_callback) - p_table = &p_var->value_callbacks; + pp = &p_var->value_callbacks; else - p_table = &p_var->list_callbacks; + pp = &p_var->list_callbacks; - for( i_entry = p_table->i_entries ; i_entry-- ; ) - { - if( p_table->p_entries[i_entry].p_callback == entry.p_callback - && p_table->p_entries[i_entry].p_data == entry.p_data ) - { - break; - } -#ifndef NDEBUG - else if( p_table->p_entries[i_entry].p_callback == entry.p_callback ) - b_found_similar = true; -#endif - } + entry = *pp; + assert(entry != NULL); - if( i_entry < 0 ) + while (entry->p_callback != match->p_callback + || entry->p_data != match->p_data) { -#ifndef NDEBUG - if( b_found_similar ) - fprintf( stderr, "Calling var_DelCallback for '%s' with the same " - "function but not the same data.", psz_name ); - vlc_assert_unreachable(); -#endif - vlc_mutex_unlock( &p_priv->var_lock ); - return; + pp = &entry->next; + entry = *pp; + assert(entry != NULL); } - TAB_ERASE(p_table->i_entries, p_table->p_entries, i_entry); - + *pp = entry->next; vlc_mutex_unlock( &p_priv->var_lock ); + free(entry); } void (var_DelCallback)(vlc_object_t *p_this, const char *psz_name, @@ -865,7 +858,7 @@ void (var_DelCallback)(vlc_object_t *p_this, const char *psz_name, entry.pf_value_callback = pf_callback; entry.p_data = p_data; - DelCallback(p_this, psz_name, entry, vlc_value_callback); + DelCallback(p_this, psz_name, &entry, vlc_value_callback); } void (var_TriggerCallback)(vlc_object_t *p_this, const char *psz_name) @@ -886,10 +879,10 @@ void (var_TriggerCallback)(vlc_object_t *p_this, const char *psz_name) void (var_AddListCallback)(vlc_object_t *p_this, const char *psz_name, vlc_list_callback_t pf_callback, void *p_data) { - callback_entry_t entry; - entry.pf_list_callback = pf_callback; - entry.p_data = p_data; + callback_entry_t *entry = xmalloc(sizeof (*entry)); + entry->pf_list_callback = pf_callback; + entry->p_data = p_data; AddCallback(p_this, psz_name, entry, vlc_list_callback); } @@ -897,10 +890,10 @@ void (var_DelListCallback)(vlc_object_t *p_this, const char *psz_name, vlc_list_callback_t pf_callback, void *p_data) { callback_entry_t entry; + entry.pf_list_callback = pf_callback; entry.p_data = p_data; - - DelCallback(p_this, psz_name, entry, vlc_list_callback); + DelCallback(p_this, psz_name, &entry, vlc_list_callback); } /** Parse a stringified option @@ -1187,8 +1180,17 @@ static void DumpVariable(const void *data, const VISIT which, const int depth) fputs(", has choices", stdout); if (var->i_type & VLC_VAR_ISCOMMAND) fputs(", command", stdout); - if (var->value_callbacks.i_entries) - printf(", %d callbacks", var->value_callbacks.i_entries); + if (var->value_callbacks != NULL) + { + size_t count = 0; + + for (callback_entry_t *entry = var->value_callbacks; + entry != NULL; + entry = entry->next) + count++; + + printf(", %zu callbacks", count); + } switch (var->i_type & VLC_VAR_CLASS) { _______________________________________________ vlc-commits mailing list vlc-commits@videolan.org https://mailman.videolan.org/listinfo/vlc-commits