While working on the python plugin, I realised that the
timeout system does not allow for notification when a timeout
is removed.  This has been fine up until now because he closures
never needed to be cleaned up.

In the python plugin, I pass through a custom structure which
needs to be cleaned up if the timeout is removed.  This is almost
certainly the cause of some horrible memory leaks for me.

The attached patch is a simple solution to the problem.  I think
it should be good enough for most situations.

I could maintain some sort of lookup inside my plugin, but I think
other plugins would benefit from this.

It is OK to go in or were there any comments?


>From 4cbf2a803d3203a71f2711851383e21688266a9b Mon Sep 17 00:00:00 2001
From: Mike Dransfield <[EMAIL PROTECTED]>
Date: Mon, 23 Apr 2007 14:26:17 +0100
Subject: [PATCH] Add remove callback to timeouts

---
 include/compiz.h |    1 +
 plugins/gconf.c  |    2 +-
 plugins/plane.c  |    2 +-
 plugins/regex.c  |    2 +-
 plugins/rotate.c |    4 ++--
 plugins/scale.c  |    1 +
 plugins/water.c  |    6 +++---
 src/display.c    |   18 ++++++++++++------
 src/event.c      |    2 +-
 src/screen.c     |    1 +
 src/window.c     |    2 +-
 11 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/include/compiz.h b/include/compiz.h
index eb3f142..4417319 100644
--- a/include/compiz.h
+++ b/include/compiz.h
@@ -942,6 +942,7 @@ compGetDisplayOptions (CompDisplay *display,
 CompTimeoutHandle
 compAddTimeout (int	     time,
 		CallBackProc callBack,
+		CallBackProc removeCallBack,
 		void	     *closure);
 
 void
diff --git a/plugins/gconf.c b/plugins/gconf.c
index 5d42f35..b3f730f 100644
--- a/plugins/gconf.c
+++ b/plugins/gconf.c
@@ -1070,7 +1070,7 @@ gconfInitDisplay (CompPlugin  *p,
     gconf_client_notify_add (gd->client, APP_NAME, gconfKeyChanged, d,
 			     NULL, NULL);
 
-    gd->timeoutHandle = compAddTimeout (KEY_CHANGE_TIMEOUT, gconfTimeout, 0);
+    gd->timeoutHandle = compAddTimeout (KEY_CHANGE_TIMEOUT, gconfTimeout, NULL, 0);
 
     return TRUE;
 }
diff --git a/plugins/plane.c b/plugins/plane.c
index e715234..6bd0b5e 100644
--- a/plugins/plane.c
+++ b/plugins/plane.c
@@ -188,7 +188,7 @@ moveViewport (CompScreen *screen,
 	ps->dest_y = -screen->y;
 
     ps->timer = SCROLL_TIME;
-    ps->timeoutHandle = compAddTimeout (SCROLL_TIME, endMove, screen);
+    ps->timeoutHandle = compAddTimeout (SCROLL_TIME, endMove, NULL, screen);
 
     damageScreen (screen);
 }
diff --git a/plugins/regex.c b/plugins/regex.c
index 1387663..9865fad 100644
--- a/plugins/regex.c
+++ b/plugins/regex.c
@@ -342,7 +342,7 @@ regexInitDisplay (CompPlugin  *p,
 
     /* one shot timeout to which will register the expression handler
        after all screens and windows have been initialized */
-    compAddTimeout (0, regexRegisterExpHanlder, (void *) d);
+    compAddTimeout (0, regexRegisterExpHanlder, NULL, (void *) d);
 
     return TRUE;
 }
diff --git a/plugins/rotate.c b/plugins/rotate.c
index bf6bb95..b52c1fc 100644
--- a/plugins/rotate.c
+++ b/plugins/rotate.c
@@ -1165,7 +1165,7 @@ rotateEdgeFlip (CompScreen      *s,
 	{
 	    if (!rs->rotateHandle)
 		rs->rotateHandle =
-		    compAddTimeout (rd->flipTime, rotateFlipLeft, s);
+		    compAddTimeout (rd->flipTime, rotateFlipLeft, NULL, s);
 
 	    rs->moving  = TRUE;
 	    rs->moveTo -= 360.0f / s->hsize;
@@ -1205,7 +1205,7 @@ rotateEdgeFlip (CompScreen      *s,
 	{
 	    if (!rs->rotateHandle)
 		rs->rotateHandle =
-		    compAddTimeout (rd->flipTime, rotateFlipRight, s);
+		    compAddTimeout (rd->flipTime, rotateFlipRight, NULL, s);
 
 	    rs->moving  = TRUE;
 	    rs->moveTo += 360.0f / s->hsize;
diff --git a/plugins/scale.c b/plugins/scale.c
index 42c777b..cc10d89 100644
--- a/plugins/scale.c
+++ b/plugins/scale.c
@@ -1774,6 +1774,7 @@ scaleHandleEvent (CompDisplay *d,
 			    ss->hoverHandle =
 				compAddTimeout (time,
 						scaleHoverTimeout,
+						NULL,
 						s);
 
 			scaleSelectWindowAt (s, x, y, focus);
diff --git a/plugins/water.c b/plugins/water.c
index d55b939..45cb004 100644
--- a/plugins/water.c
+++ b/plugins/water.c
@@ -1347,7 +1347,7 @@ waterToggleRain (CompDisplay     *d,
 	    int delay;
 
 	    delay = wd->opt[WATER_DISPLAY_OPTION_RAIN_DELAY].value.i;
-	    ws->rainHandle = compAddTimeout (delay, waterRainTimeout, s);
+	    ws->rainHandle = compAddTimeout (delay, waterRainTimeout, NULL, s);
 	}
 	else
 	{
@@ -1378,7 +1378,7 @@ waterToggleWiper (CompDisplay     *d,
 	    int delay;
 
 	    delay = 2000;
-	    ws->wiperHandle = compAddTimeout (delay, waterWiperTimeout, s);
+	    ws->wiperHandle = compAddTimeout (delay, waterWiperTimeout, NULL, s);
 	}
 	else
 	{
@@ -1586,7 +1586,7 @@ waterSetDisplayOption (CompPlugin      *plugin,
 		    continue;
 
 		compRemoveTimeout (ws->rainHandle);
-		ws->rainHandle = compAddTimeout (value->i, waterRainTimeout, s);
+		ws->rainHandle = compAddTimeout (value->i, waterRainTimeout, NULL, s);
 	    }
 	    return TRUE;
 	}
diff --git a/src/display.c b/src/display.c
index ee092bf..6c4aa27 100644
--- a/src/display.c
+++ b/src/display.c
@@ -55,6 +55,7 @@ typedef struct _CompTimeout {
     int			time;
     int			left;
     CallBackProc	callBack;
+    CallBackProc	removeCallBack;
     void		*closure;
     CompTimeoutHandle   handle;
 } CompTimeout;
@@ -863,7 +864,7 @@ setDisplayOption (CompDisplay     *display,
 		compRemoveTimeout (display->pingHandle);
 
 	    display->pingHandle =
-		compAddTimeout (o->value.i, pingTimeout, display);
+		compAddTimeout (o->value.i, pingTimeout, NULL, display);
 	    return TRUE;
 	}
 	break;
@@ -1058,6 +1059,7 @@ addTimeout (CompTimeout *timeout)
 CompTimeoutHandle
 compAddTimeout (int	     time,
 		CallBackProc callBack,
+		CallBackProc removeCallBack,
 		void	     *closure)
 {
     CompTimeout *timeout;
@@ -1066,10 +1068,11 @@ compAddTimeout (int	     time,
     if (!timeout)
 	return 0;
 
-    timeout->time     = time;
-    timeout->callBack = callBack;
-    timeout->closure  = closure;
-    timeout->handle   = lastTimeoutHandle++;
+    timeout->time           = time;
+    timeout->callBack       = callBack;
+    timeout->removeCallBack = removeCallBack;
+    timeout->closure        = closure;
+    timeout->handle         = lastTimeoutHandle++;
 
     if (lastTimeoutHandle == MAXSHORT)
 	lastTimeoutHandle = 1;
@@ -1102,6 +1105,9 @@ compRemoveTimeout (CompTimeoutHandle handle)
 	else
 	    timeouts = t->next;
 
+	if (t->removeCallBack)
+	    (*t->removeCallBack) (t->closure);
+
 	free (t);
     }
 }
@@ -2548,7 +2554,7 @@ addDisplay (char *name)
 
     d->pingHandle =
 	compAddTimeout (d->opt[COMP_DISPLAY_OPTION_PING_DELAY].value.i,
-			pingTimeout, d);
+			pingTimeout, NULL, d);
 
     return TRUE;
 }
diff --git a/src/event.c b/src/event.c
index 52cae89..3e7936c 100644
--- a/src/event.c
+++ b/src/event.c
@@ -2022,7 +2022,7 @@ handleEvent (CompDisplay *d,
 			    {
 				d->autoRaiseWindow = w->id;
 				d->autoRaiseHandle =
-				    compAddTimeout (delay, autoRaiseTimeout, d);
+				    compAddTimeout (delay, autoRaiseTimeout, NULL, d);
 			    }
 			    else
 				updateWindowAttributes (w, 
diff --git a/src/screen.c b/src/screen.c
index 68e8f41..e8b541b 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -674,6 +674,7 @@ addSequence (CompScreen        *screen,
     if (!screen->startupSequenceTimeoutHandle)
 	compAddTimeout (1000,
 			startupSequenceTimeout,
+			NULL,
 			screen);
 
     updateStartupFeedback (screen);
diff --git a/src/window.c b/src/window.c
index 8d29530..74fb51b 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2580,7 +2580,7 @@ sendSyncRequest (CompWindow *w)
     w->syncBorderWidth = w->serverBorderWidth;
 
     if (!w->syncWaitHandle)
-	w->syncWaitHandle = compAddTimeout (1000, syncWaitTimeout, w);
+	w->syncWaitHandle = compAddTimeout (1000, syncWaitTimeout, NULL, w);
 }
 
 void
-- 
1.5.1

_______________________________________________
compiz mailing list
compiz@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/compiz

Reply via email to