From b86451dc76abfc5a22703de0e51635416c02200d Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 13 Feb 2009 19:58:17 +0100 Subject: [PATCH] Pass GTimeVal around for performance reasons Get the current time only once and pass it around so that sessions don't have to get the current time anymore. Add experimental support for a GSource that dispatches when the session needs to be cleaned up. --- gst/rtsp-server/rtsp-session-pool.c | 119 +++++++++++++++++++++++++++- gst/rtsp-server/rtsp-session-pool.h | 16 ++++ 2 files changed, 132 insertions(+), 3 deletions(-) diff --git a/gst/rtsp-server/rtsp-session-pool.c b/gst/rtsp-server/rtsp-session-pool.c index d32b43fd42..44d749b605 100644 --- a/gst/rtsp-server/rtsp-session-pool.c +++ b/gst/rtsp-server/rtsp-session-pool.c @@ -58,6 +58,7 @@ gst_rtsp_session_pool_class_init (GstRTSPSessionPoolClass * klass) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); klass->create_session_id = create_session_id; + } static void @@ -350,9 +351,9 @@ gst_rtsp_session_pool_remove (GstRTSPSessionPool *pool, GstRTSPSession *sess) } static gboolean -cleanup_func (gchar *sessionid, GstRTSPSession *sess, GstRTSPSessionPool *pool) +cleanup_func (gchar *sessionid, GstRTSPSession *sess, GTimeVal *now) { - return gst_rtsp_session_is_expired (sess); + return gst_rtsp_session_is_expired (sess, now); } /** @@ -368,12 +369,124 @@ guint gst_rtsp_session_pool_cleanup (GstRTSPSessionPool *pool) { guint result; + GTimeVal now; g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), 0); + g_get_current_time (&now); + g_mutex_lock (pool->lock); - result = g_hash_table_foreach_remove (pool->sessions, (GHRFunc) cleanup_func, pool); + result = g_hash_table_foreach_remove (pool->sessions, (GHRFunc) cleanup_func, &now); g_mutex_unlock (pool->lock); return result; } + +typedef struct +{ + GSource source; + GstRTSPSessionPool *pool; + gint timeout; +} GstPoolSource; + +static void +collect_timeout (gchar *sessionid, GstRTSPSession *sess, GstPoolSource *psrc) +{ + gint timeout; + GTimeVal now; + + g_source_get_current_time ((GSource*)psrc, &now); + + timeout = gst_rtsp_session_next_timeout (sess, &now); + g_message ("%p: next timeout: %d", sess, timeout); + if (psrc->timeout == -1 || timeout < psrc->timeout) + psrc->timeout = timeout; +} + +static gboolean +gst_pool_source_prepare (GSource * source, gint * timeout) +{ + GstPoolSource *psrc; + gboolean result; + + psrc = (GstPoolSource *) source; + psrc->timeout = -1; + + g_mutex_lock (psrc->pool->lock); + g_hash_table_foreach (psrc->pool->sessions, (GHFunc) collect_timeout, psrc); + g_mutex_unlock (psrc->pool->lock); + + if (timeout) + *timeout = psrc->timeout; + + result = psrc->timeout == 0; + + g_message ("prepare %d, %d", psrc->timeout, result); + + return result; +} + +static gboolean +gst_pool_source_check (GSource * source) +{ + g_message ("check"); + + return gst_pool_source_prepare (source, NULL); +} + +static gboolean +gst_pool_source_dispatch (GSource * source, GSourceFunc callback, + gpointer user_data) +{ + gboolean res; + GstPoolSource *psrc = (GstPoolSource *) source; + GstRTSPSessionPoolFunc func = (GstRTSPSessionPoolFunc) callback; + + g_message ("dispatch"); + + if (func) + res = func (psrc->pool, user_data); + else + res = FALSE; + + return res; +} + +static void +gst_pool_source_finalize (GSource * source) +{ + GstPoolSource *psrc = (GstPoolSource *) source; + + g_message ("finalize %p", psrc); + + g_object_unref (psrc->pool); + psrc->pool = NULL; +} + +static GSourceFuncs gst_pool_source_funcs = { + gst_pool_source_prepare, + gst_pool_source_check, + gst_pool_source_dispatch, + gst_pool_source_finalize +}; + +/** + * gst_rtsp_session_pool_create_watch: + * @pool: a #GstRTSPSessionPool + * + * A GSource that will be dispatched when the session should be cleaned up. + */ +GSource * +gst_rtsp_session_pool_create_watch (GstRTSPSessionPool *pool) +{ + GstPoolSource *source; + + g_return_val_if_fail (GST_IS_RTSP_SESSION_POOL (pool), NULL); + + source = (GstPoolSource *) g_source_new (&gst_pool_source_funcs, + sizeof (GstPoolSource)); + source->pool = g_object_ref (pool); + + return (GSource *) source; +} + diff --git a/gst/rtsp-server/rtsp-session-pool.h b/gst/rtsp-server/rtsp-session-pool.h index dba8b764f6..7c387cd36e 100644 --- a/gst/rtsp-server/rtsp-session-pool.h +++ b/gst/rtsp-server/rtsp-session-pool.h @@ -67,6 +67,21 @@ struct _GstRTSPSessionPoolClass { gchar * (*create_session_id) (GstRTSPSessionPool *pool); }; +/** + * GstRTSPSessionPoolFunc: + * @pool: a #GstRTSPSessionPool object + * @user_data: user data that has been given when registering the handler + * + * The function that will be called from the GSource watch on the session pool. + * + * The function will be called when the pool must be cleaned up because one or + * more sessions timed out. + * + * Returns: %FALSe if the source should be removed. + */ +typedef gboolean (*GstRTSPSessionPoolFunc) (GstRTSPSessionPool *pool, gpointer user_data); + + GType gst_rtsp_session_pool_get_type (void); /* creating a session pool */ @@ -87,6 +102,7 @@ gboolean gst_rtsp_session_pool_remove (GstRTSPSessionPoo /* perform session maintenance */ guint gst_rtsp_session_pool_cleanup (GstRTSPSessionPool *pool); +GSource * gst_rtsp_session_pool_create_watch (GstRTSPSessionPool *pool); G_END_DECLS