Commit e783869a authored by JP Dinger's avatar JP Dinger

async event handling: Push is now O(1) instead of O(n).

parent ce00864d
...@@ -17,9 +17,9 @@ ...@@ -17,9 +17,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License along
* along with this program; if not, write to the Free Software * with this program; if not, write to the Free Software Foundation, Inc.,
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/ *****************************************************************************/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
...@@ -40,13 +40,16 @@ struct queue_elmt { ...@@ -40,13 +40,16 @@ struct queue_elmt {
}; };
struct libvlc_event_async_queue { struct libvlc_event_async_queue {
struct queue_elmt * elements; struct queue_elmt *first_elmt, *last_elmt;
vlc_mutex_t lock; vlc_mutex_t lock;
vlc_cond_t signal; vlc_cond_t signal;
vlc_thread_t thread; vlc_thread_t thread;
bool is_idle; bool is_idle;
vlc_cond_t signal_idle; vlc_cond_t signal_idle;
vlc_threadvar_t is_asynch_dispatch_thread_var; vlc_threadvar_t is_asynch_dispatch_thread_var;
#ifndef NDEBUG
long count;
#endif
}; };
/* /*
...@@ -71,37 +74,29 @@ static inline bool current_thread_is_asynch_thread(libvlc_event_manager_t * p_em ...@@ -71,37 +74,29 @@ static inline bool current_thread_is_asynch_thread(libvlc_event_manager_t * p_em
} }
/* Lock must be held */ /* Lock must be held */
static void push(libvlc_event_manager_t * p_em, libvlc_event_listener_t * listener, libvlc_event_t * event) static void push(libvlc_event_manager_t * p_em,
libvlc_event_listener_t * listener, libvlc_event_t * event)
{ {
#ifndef NDEBUG
static const long MaxQueuedItem = 300000;
long count = 0;
#endif
struct queue_elmt * elmt = malloc(sizeof(struct queue_elmt)); struct queue_elmt * elmt = malloc(sizeof(struct queue_elmt));
elmt->listener = *listener; elmt->listener = *listener;
elmt->event = *event; elmt->event = *event;
elmt->next = NULL; elmt->next = NULL;
/* Append to the end of the queue */ /* Append to the end of the queue */
struct queue_elmt * iter = queue(p_em)->elements; if(!queue(p_em)->first_elmt)
if(!iter) queue(p_em)->first_elmt = elmt;
{ else
queue(p_em)->elements = elmt; queue(p_em)->last_elmt->next = elmt;
return; queue(p_em)->last_elmt = elmt;
}
while (iter->next) {
iter = iter->next;
#ifndef NDEBUG #ifndef NDEBUG
if(count++ > MaxQueuedItem) enum { MaxQueueSize = 300000 };
if(queue(p_em)->count++ > MaxQueueSize)
{ {
fprintf(stderr, "Warning: libvlc event overflow.\n"); fprintf(stderr, "Warning: libvlc event overflow.\n");
abort(); abort();
} }
#endif #endif
}
iter->next = elmt;
} }
static inline void queue_lock(libvlc_event_manager_t * p_em) static inline void queue_lock(libvlc_event_manager_t * p_em)
...@@ -115,16 +110,23 @@ static inline void queue_unlock(libvlc_event_manager_t * p_em) ...@@ -115,16 +110,23 @@ static inline void queue_unlock(libvlc_event_manager_t * p_em)
} }
/* Lock must be held */ /* Lock must be held */
static bool pop(libvlc_event_manager_t * p_em, libvlc_event_listener_t * listener, libvlc_event_t * event) static bool pop(libvlc_event_manager_t * p_em,
libvlc_event_listener_t * listener, libvlc_event_t * event)
{ {
if(!queue(p_em)->elements) if(!queue(p_em)->first_elmt)
return false; /* No elements */ return false; /* No first_elmt */
struct queue_elmt * elmt = queue(p_em)->first_elmt;
*listener = elmt->listener;
*event = elmt->event;
queue(p_em)->first_elmt = elmt->next;
if( !elmt->next ) queue(p_em)->last_elmt=NULL;
*listener = queue(p_em)->elements->listener; #ifndef NDEBUG
*event = queue(p_em)->elements->event; queue(p_em)->count--;
#endif
struct queue_elmt * elmt = queue(p_em)->elements;
queue(p_em)->elements = elmt->next;
free(elmt); free(elmt);
return true; return true;
} }
...@@ -132,24 +134,28 @@ static bool pop(libvlc_event_manager_t * p_em, libvlc_event_listener_t * listene ...@@ -132,24 +134,28 @@ static bool pop(libvlc_event_manager_t * p_em, libvlc_event_listener_t * listene
/* Lock must be held */ /* Lock must be held */
static void pop_listener(libvlc_event_manager_t * p_em, libvlc_event_listener_t * listener) static void pop_listener(libvlc_event_manager_t * p_em, libvlc_event_listener_t * listener)
{ {
struct queue_elmt * iter = queue(p_em)->elements; struct queue_elmt * iter = queue(p_em)->first_elmt;
struct queue_elmt * prev = NULL; struct queue_elmt * prev = NULL;
while (iter) { while (iter) {
if(listeners_are_equal(&iter->listener, listener)) if(listeners_are_equal(&iter->listener, listener))
{ {
struct queue_elmt * to_delete = iter; struct queue_elmt * to_delete = iter;
if(!prev) if(!prev)
queue(p_em)->elements = to_delete->next; queue(p_em)->first_elmt = to_delete->next;
else else
prev->next = to_delete->next; prev->next = to_delete->next;
iter = to_delete->next; iter = to_delete->next;
free(to_delete); free(to_delete);
#ifndef NDEBUG
queue(p_em)->count--;
#endif
} }
else { else {
prev = iter; prev = iter;
iter = iter->next; iter = iter->next;
} }
} }
queue(p_em)->last_elmt=prev;
} }
/************************************************************************** /**************************************************************************
...@@ -180,7 +186,7 @@ libvlc_event_async_fini(libvlc_event_manager_t * p_em) ...@@ -180,7 +186,7 @@ libvlc_event_async_fini(libvlc_event_manager_t * p_em)
vlc_cond_destroy(&queue(p_em)->signal_idle); vlc_cond_destroy(&queue(p_em)->signal_idle);
vlc_threadvar_delete(&queue(p_em)->is_asynch_dispatch_thread_var); vlc_threadvar_delete(&queue(p_em)->is_asynch_dispatch_thread_var);
struct queue_elmt * iter = queue(p_em)->elements; struct queue_elmt * iter = queue(p_em)->first_elmt;
while (iter) { while (iter) {
struct queue_elmt * elemt_to_delete = iter; struct queue_elmt * elemt_to_delete = iter;
iter = iter->next; iter = iter->next;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment