glib: Refactor Source, Idle and Timeout classes

Turn Source.source_handlers into a private generic Dictionary, and add
the necessary methods to allow Idle and Timeout to add and remove
entries from it.

This improves the encapsulation of the Source class, and factors
into it some code that was previously duplicated in Idle and Timeout.
This commit is contained in:
Bertrand Lorentz 2014-07-05 15:38:34 +02:00
parent 11920f2add
commit 813f56e00a
3 changed files with 47 additions and 56 deletions

View file

@ -37,7 +37,6 @@ namespace GLib {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)] [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
delegate bool IdleHandlerInternal (); delegate bool IdleHandlerInternal ();
internal class IdleProxy : SourceProxy { internal class IdleProxy : SourceProxy {
public IdleProxy (IdleHandler real) public IdleProxy (IdleHandler real)
{ {
@ -96,8 +95,7 @@ namespace GLib {
{ {
IdleProxy p = new IdleProxy (hndlr); IdleProxy p = new IdleProxy (hndlr);
p.ID = g_idle_add ((IdleHandlerInternal) p.proxy_handler, IntPtr.Zero); p.ID = g_idle_add ((IdleHandlerInternal) p.proxy_handler, IntPtr.Zero);
lock (Source.source_handlers) Source.AddSourceHandler (p.ID, p);
Source.source_handlers [p.ID] = p;
return p.ID; return p.ID;
} }
@ -109,15 +107,11 @@ namespace GLib {
{ {
IdleProxy p = new IdleProxy (hndlr); IdleProxy p = new IdleProxy (hndlr);
p.ID = g_idle_add_full ((int)priority, (IdleHandlerInternal)p.proxy_handler, IntPtr.Zero, null); p.ID = g_idle_add_full ((int)priority, (IdleHandlerInternal)p.proxy_handler, IntPtr.Zero, null);
lock (Source.source_handlers) Source.AddSourceHandler (p.ID, p);
Source.source_handlers [p.ID] = p;
return p.ID; return p.ID;
} }
[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
static extern bool g_source_remove (uint id);
public static void Remove (uint id) public static void Remove (uint id)
{ {
Source.Remove (id); Source.Remove (id);
@ -125,24 +119,7 @@ namespace GLib {
public static bool Remove (IdleHandler hndlr) public static bool Remove (IdleHandler hndlr)
{ {
bool result = false; return Source.RemoveSourceHandler (hndlr);
List<uint> keys = new List<uint> ();
lock (Source.source_handlers) {
foreach (uint code in Source.source_handlers.Keys) {
IdleProxy p = Source.source_handlers [code] as IdleProxy;
if (p != null && p.real_handler == hndlr) {
keys.Add (code);
result = g_source_remove (code);
}
}
foreach (object key in keys)
Source.source_handlers.Remove (key);
}
return result;
} }
} }
} }

View file

@ -23,6 +23,7 @@ namespace GLib {
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
public delegate bool GSourceFunc (); public delegate bool GSourceFunc ();
@ -37,8 +38,7 @@ namespace GLib {
internal void Remove () internal void Remove ()
{ {
lock (Source.source_handlers) Source.RemoveSourceHandler (ID);
Source.source_handlers.Remove (ID);
real_handler = null; real_handler = null;
proxy_handler = null; proxy_handler = null;
} }
@ -46,7 +46,7 @@ namespace GLib {
public partial class Source : GLib.Opaque { public partial class Source : GLib.Opaque {
internal static Hashtable source_handlers = new Hashtable (); private static IDictionary<uint, SourceProxy> source_handlers = new Dictionary<uint, SourceProxy> ();
private Source () {} private Source () {}
@ -86,6 +86,43 @@ namespace GLib {
GLib.Timeout.Add (50, new GLib.TimeoutHandler (info.Handler)); GLib.Timeout.Add (50, new GLib.TimeoutHandler (info.Handler));
} }
internal static void AddSourceHandler (uint id, SourceProxy proxy)
{
lock (Source.source_handlers) {
source_handlers [id] = proxy;
}
}
internal static void RemoveSourceHandler (uint id)
{
lock (Source.source_handlers) {
source_handlers.Remove (id);
}
}
internal static bool RemoveSourceHandler (Delegate hndlr)
{
bool result = false;
List<uint> keys = new List<uint> ();
lock (source_handlers) {
foreach (uint code in source_handlers.Keys) {
var p = Source.source_handlers [code];
if (p != null && p.real_handler == hndlr) {
keys.Add (code);
result = g_source_remove (code);
}
}
foreach (var key in keys) {
Source.RemoveSourceHandler (key);
}
}
return result;
}
[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)] [DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
static extern bool g_source_remove (uint tag); static extern bool g_source_remove (uint tag);

View file

@ -91,8 +91,7 @@ namespace GLib {
TimeoutProxy p = new TimeoutProxy (hndlr); TimeoutProxy p = new TimeoutProxy (hndlr);
p.ID = g_timeout_add (interval, (TimeoutHandlerInternal) p.proxy_handler, IntPtr.Zero); p.ID = g_timeout_add (interval, (TimeoutHandlerInternal) p.proxy_handler, IntPtr.Zero);
lock (Source.source_handlers) Source.AddSourceHandler (p.ID, p);
Source.source_handlers [p.ID] = p;
return p.ID; return p.ID;
} }
@ -105,8 +104,7 @@ namespace GLib {
TimeoutProxy p = new TimeoutProxy (hndlr); TimeoutProxy p = new TimeoutProxy (hndlr);
p.ID = g_timeout_add_full ((int)priority, interval, (TimeoutHandlerInternal) p.proxy_handler, IntPtr.Zero, null); p.ID = g_timeout_add_full ((int)priority, interval, (TimeoutHandlerInternal) p.proxy_handler, IntPtr.Zero, null);
lock (Source.source_handlers) Source.AddSourceHandler (p.ID, p);
Source.source_handlers [p.ID] = p;
return p.ID; return p.ID;
} }
@ -119,8 +117,7 @@ namespace GLib {
TimeoutProxy p = new TimeoutProxy (hndlr); TimeoutProxy p = new TimeoutProxy (hndlr);
p.ID = g_timeout_add_seconds (interval, (TimeoutHandlerInternal) p.proxy_handler, IntPtr.Zero); p.ID = g_timeout_add_seconds (interval, (TimeoutHandlerInternal) p.proxy_handler, IntPtr.Zero);
lock (Source.source_handlers) Source.AddSourceHandler (p.ID, p);
Source.source_handlers [p.ID] = p;
return p.ID; return p.ID;
} }
@ -130,29 +127,9 @@ namespace GLib {
Source.Remove (id); Source.Remove (id);
} }
[DllImport (Global.GLibNativeDll, CallingConvention = CallingConvention.Cdecl)]
static extern bool g_source_remove (uint id);
public static bool Remove (TimeoutHandler hndlr) public static bool Remove (TimeoutHandler hndlr)
{ {
bool result = false; return Source.RemoveSourceHandler (hndlr);
List<uint> keys = new List<uint> ();
lock (Source.source_handlers) {
foreach (uint code in Source.source_handlers.Keys) {
TimeoutProxy p = Source.source_handlers [code] as TimeoutProxy;
if (p != null && p.real_handler == hndlr) {
keys.Add (code);
result = g_source_remove (code);
}
}
foreach (object key in keys)
Source.source_handlers.Remove (key);
}
return result;
} }
} }
} }