[Monodevelop-patches-list] r2057 - in trunk/MonoDevelop/Core/src/Main/Base: . Services/DispatchService
commit-watcher at mono-cvs.ximian.com
commit-watcher at mono-cvs.ximian.com
Mon Dec 6 15:40:46 EST 2004
Author: lluis
Date: 2004-12-06 15:40:45 -0500 (Mon, 06 Dec 2004)
New Revision: 2057
Added:
trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/AsyncDispatchAttribute.cs
trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/FreeDispatchAttribute.cs
trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/GuiSyncContext.cs
trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/GuiSyncObject.cs
trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/SyncContext.cs
trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/SyncContextAttribute.cs
trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/SyncObject.cs
Modified:
trunk/MonoDevelop/Core/src/Main/Base/ChangeLog
trunk/MonoDevelop/Core/src/Main/Base/Makefile.am
trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/DispatchService.cs
Log:
* Services/DispatchService/DispatchService.cs: Added support for
synchronous dispatch to the gui thread.
* Services/DispatchService/AsyncDispatchAttribute.cs:
* Services/DispatchService/SyncContext.cs:
* Services/DispatchService/SyncObject.cs:
* Services/DispatchService/FreeDispatchAttribute.cs:
* Services/DispatchService/SyncContextAttribute.cs:
* Services/DispatchService/GuiSyncContext.cs:
* Services/DispatchService/GuiSyncObject.cs: New classes that support
some new dispatch features.
2004-12-06 Lluis Sanchez Gual <lluis at novell.com>
Modified: trunk/MonoDevelop/Core/src/Main/Base/ChangeLog
===================================================================
--- trunk/MonoDevelop/Core/src/Main/Base/ChangeLog 2004-12-06 17:00:46 UTC (rev 2056)
+++ trunk/MonoDevelop/Core/src/Main/Base/ChangeLog 2004-12-06 20:40:45 UTC (rev 2057)
@@ -1,5 +1,18 @@
2004-12-06 Lluis Sanchez Gual <lluis at novell.com>
+ * Services/DispatchService/DispatchService.cs: Added support for
+ synchronous dispatch to the gui thread.
+ * Services/DispatchService/AsyncDispatchAttribute.cs:
+ * Services/DispatchService/SyncContext.cs:
+ * Services/DispatchService/SyncObject.cs:
+ * Services/DispatchService/FreeDispatchAttribute.cs:
+ * Services/DispatchService/SyncContextAttribute.cs:
+ * Services/DispatchService/GuiSyncContext.cs:
+ * Services/DispatchService/GuiSyncObject.cs: New classes that support
+ some new dispatch features.
+
+2004-12-06 Lluis Sanchez Gual <lluis at novell.com>
+
* *.cs: Removed remaining calls to ServiceManager.GetService.
2004-12-06 Lluis Sanchez Gual <lluis at novell.com>
Modified: trunk/MonoDevelop/Core/src/Main/Base/Makefile.am
===================================================================
--- trunk/MonoDevelop/Core/src/Main/Base/Makefile.am 2004-12-06 17:00:46 UTC (rev 2056)
+++ trunk/MonoDevelop/Core/src/Main/Base/Makefile.am 2004-12-06 20:40:45 UTC (rev 2057)
@@ -209,7 +209,14 @@
Services/MonodocService.cs \
Services/IDebuggerService.cs \
Services/SystemAssemblyService.cs \
+Services/DispatchService/AsyncDispatchAttribute.cs \
Services/DispatchService/DispatchService.cs \
+Services/DispatchService/FreeDispatchAttribute.cs \
+Services/DispatchService/GuiSyncContext.cs \
+Services/DispatchService/GuiSyncObject.cs \
+Services/DispatchService/SyncContext.cs \
+Services/DispatchService/SyncContextAttribute.cs \
+Services/DispatchService/SyncObject.cs \
Services/Runtime.cs \
Internal/Undo/IUndoableOperation.cs \
Internal/Undo/UndoStack.cs \
Added: trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/AsyncDispatchAttribute.cs
===================================================================
--- trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/AsyncDispatchAttribute.cs 2004-12-06 17:00:46 UTC (rev 2056)
+++ trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/AsyncDispatchAttribute.cs 2004-12-06 20:40:45 UTC (rev 2057)
@@ -0,0 +1,15 @@
+// <file>
+// <copyright see="prj:///doc/copyright.txt"/>
+// <license see="prj:///doc/license.txt"/>
+// <owner name="Lluis Sanchez Gual" email="lluis at ximian.com"/>
+// <version value="$version"/>
+// </file>
+
+using System;
+
+namespace MonoDevelop.Services
+{
+ public class AsyncDispatchAttribute: Attribute
+ {
+ }
+}
Modified: trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/DispatchService.cs
===================================================================
--- trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/DispatchService.cs 2004-12-06 17:00:46 UTC (rev 2056)
+++ trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/DispatchService.cs 2004-12-06 20:40:45 UTC (rev 2057)
@@ -13,33 +13,69 @@
ArrayList arrGuiQueue;
Thread thrBackground;
uint iIdle = 0;
+ GLib.IdleHandler handler;
+ static int guiThreadId;
+ static GuiSyncContext guiContext;
+ const string errormsg = "An exception was thrown while dispatching a method call in the UI thread.";
+ internal static bool DispatchDebug;
public override void InitializeService ()
{
+ guiContext = new GuiSyncContext ();
+ SyncContext.SetContext (guiContext);
+
+ guiThreadId = AppDomain.GetCurrentThreadId();
+
+ handler = new GLib.IdleHandler (guiDispatcher);
arrBackgroundQueue = new ArrayList ();
arrGuiQueue = new ArrayList ();
thrBackground = new Thread (new ThreadStart (backgroundDispatcher));
thrBackground.IsBackground = true;
thrBackground.Priority = ThreadPriority.Lowest;
thrBackground.Start ();
+ DispatchDebug = Environment.GetEnvironmentVariable ("MONODEVELOP_DISPATCH_DEBUG") != null;
}
public void GuiDispatch (MessageHandler cb)
{
- arrGuiQueue.Add (new GenericMessageContainer (cb));
+ arrGuiQueue.Add (new GenericMessageContainer (cb, false));
UpdateIdle ();
}
public void GuiDispatch (StatefulMessageHandler cb, object state)
{
- arrGuiQueue.Add (new StatefulMessageContainer (cb, state));
+ arrGuiQueue.Add (new StatefulMessageContainer (cb, state, false));
UpdateIdle ();
}
+ public void GuiSyncDispatch (MessageHandler cb)
+ {
+ GenericMessageContainer mc = new GenericMessageContainer (cb, true);
+ lock (mc) {
+ arrGuiQueue.Add (mc);
+ UpdateIdle ();
+ Monitor.Wait (mc);
+ }
+ if (mc.Exception != null)
+ throw new Exception (errormsg, mc.Exception);
+ }
+
+ public void GuiSyncDispatch (StatefulMessageHandler cb, object state)
+ {
+ StatefulMessageContainer mc = new StatefulMessageContainer (cb, state, true);
+ lock (mc) {
+ arrGuiQueue.Add (mc);
+ UpdateIdle ();
+ Monitor.Wait (mc);
+ }
+ if (mc.Exception != null)
+ throw new Exception (errormsg, mc.Exception);
+ }
+
void UpdateIdle ()
{
if (iIdle == 0) {
- iIdle = GLib.Idle.Add (new GLib.IdleHandler (guiDispatcher));
+ iIdle = GLib.Idle.Add (handler);
/* This code is required because for some
* reason the idle handler is run once
* before being set, so you get a idle
@@ -50,15 +86,31 @@
iIdle = 0;
}
}
-
+
+ public static bool IsGuiThread
+ {
+ get { return guiThreadId == AppDomain.GetCurrentThreadId(); }
+ }
+
+ public static void AssertGuiThread ()
+ {
+ if (guiThreadId != AppDomain.GetCurrentThreadId())
+ throw new InvalidOperationException ("This method can only be called in the GUI thread");
+ }
+
+ public static Delegate GuiDispatch (Delegate del)
+ {
+ return guiContext.CreateSynchronizedDelegate (del);
+ }
+
public void BackgroundDispatch (MessageHandler cb)
{
- arrBackgroundQueue.Add (new GenericMessageContainer (cb));
+ arrBackgroundQueue.Add (new GenericMessageContainer (cb, false));
}
public void BackgroundDispatch (StatefulMessageHandler cb, object state)
{
- arrBackgroundQueue.Add (new StatefulMessageContainer (cb, state));
+ arrBackgroundQueue.Add (new StatefulMessageContainer (cb, state, false));
//thrBackground.Resume ();
}
@@ -73,8 +125,14 @@
msg = (GenericMessageContainer)arrGuiQueue[0];
arrGuiQueue.RemoveAt (0);
}
- if (msg != null)
+ if (msg != null) {
msg.Run ();
+ if (msg.IsSynchronous)
+ lock (msg) Monitor.PulseAll (msg);
+ else if (msg.Exception != null)
+ HandlerError (msg);
+ }
+
if (arrGuiQueue.Count == 0) {
iIdle = 0;
return false;
@@ -95,10 +153,25 @@
msg = (GenericMessageContainer)arrBackgroundQueue[0];
arrBackgroundQueue.RemoveAt (0);
}
- if (msg != null)
+ if (msg != null) {
msg.Run ();
+ if (msg.Exception != null)
+ HandlerError (msg);
+ }
}
}
+
+ private void HandlerError (GenericMessageContainer msg)
+ {
+ Console.WriteLine (errormsg);
+ Console.WriteLine (msg.Exception);
+ if (msg.CallerStack != null) {
+ Console.WriteLine ("\nCaller stack:");
+ Console.WriteLine (msg.CallerStack);
+ }
+ else
+ Console.WriteLine ("\n\nCaller stack not available. Define the environment variable MONODEVELOP_DISPATCH_DEBUG to enable caller stack capture.");
+ }
}
public delegate void MessageHandler ();
@@ -107,18 +180,43 @@
class GenericMessageContainer
{
MessageHandler callback;
+ protected Exception ex;
+ protected bool isSynchronous;
+ protected string callerStack;
protected GenericMessageContainer () { }
- public GenericMessageContainer (MessageHandler cb)
+ public GenericMessageContainer (MessageHandler cb, bool isSynchronous)
{
callback = cb;
+ this.isSynchronous = isSynchronous;
+ if (DispatchService.DispatchDebug) callerStack = Environment.StackTrace;
}
public virtual void Run ()
{
- callback ();
+ try {
+ callback ();
+ }
+ catch (Exception e) {
+ ex = e;
+ }
}
+
+ public Exception Exception
+ {
+ get { return ex; }
+ }
+
+ public bool IsSynchronous
+ {
+ get { return isSynchronous; }
+ }
+
+ public string CallerStack
+ {
+ get { return callerStack; }
+ }
}
class StatefulMessageContainer : GenericMessageContainer
@@ -126,15 +224,23 @@
object data;
StatefulMessageHandler callback;
- public StatefulMessageContainer (StatefulMessageHandler cb, object state)
+ public StatefulMessageContainer (StatefulMessageHandler cb, object state, bool isSynchronous)
{
data = state;
callback = cb;
+ this.isSynchronous = isSynchronous;
+ if (DispatchService.DispatchDebug) callerStack = Environment.StackTrace;
}
public override void Run ()
{
- callback (data);
+ try {
+ callback (data);
+ }
+ catch (Exception e) {
+ ex = e;
+ }
}
}
+
}
Added: trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/FreeDispatchAttribute.cs
===================================================================
--- trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/FreeDispatchAttribute.cs 2004-12-06 17:00:46 UTC (rev 2056)
+++ trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/FreeDispatchAttribute.cs 2004-12-06 20:40:45 UTC (rev 2057)
@@ -0,0 +1,15 @@
+// <file>
+// <copyright see="prj:///doc/copyright.txt"/>
+// <license see="prj:///doc/license.txt"/>
+// <owner name="Lluis Sanchez Gual" email="lluis at ximian.com"/>
+// <version value="$version"/>
+// </file>
+
+using System;
+
+namespace MonoDevelop.Services
+{
+ public class FreeDispatchAttribute: Attribute
+ {
+ }
+}
Added: trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/GuiSyncContext.cs
===================================================================
--- trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/GuiSyncContext.cs 2004-12-06 17:00:46 UTC (rev 2056)
+++ trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/GuiSyncContext.cs 2004-12-06 20:40:45 UTC (rev 2057)
@@ -0,0 +1,36 @@
+// <file>
+// <copyright see="prj:///doc/copyright.txt"/>
+// <license see="prj:///doc/license.txt"/>
+// <owner name="Lluis Sanchez Gual" email="lluis at ximian.com"/>
+// <version value="$version"/>
+// </file>
+
+using System;
+
+namespace MonoDevelop.Services
+{
+ public class GuiSyncContext: SyncContext
+ {
+ DispatchService dispatcher;
+
+ public override void Dispatch (StatefulMessageHandler cb, object ob)
+ {
+ if (dispatcher == null)
+ dispatcher = Runtime.DispatchService;
+
+ if (DispatchService.IsGuiThread)
+ cb (ob);
+ else {
+ dispatcher.GuiSyncDispatch (cb, ob);
+ }
+ }
+
+ public override void AsyncDispatch (StatefulMessageHandler cb, object ob)
+ {
+ if (dispatcher == null)
+ dispatcher = Runtime.DispatchService;
+
+ dispatcher.GuiDispatch (cb, ob);
+ }
+ }
+}
Added: trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/GuiSyncObject.cs
===================================================================
--- trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/GuiSyncObject.cs 2004-12-06 17:00:46 UTC (rev 2056)
+++ trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/GuiSyncObject.cs 2004-12-06 20:40:45 UTC (rev 2057)
@@ -0,0 +1,16 @@
+// <file>
+// <copyright see="prj:///doc/copyright.txt"/>
+// <license see="prj:///doc/license.txt"/>
+// <owner name="Lluis Sanchez Gual" email="lluis at ximian.com"/>
+// <version value="$version"/>
+// </file>
+
+using System;
+
+namespace MonoDevelop.Services
+{
+ [SyncContext (typeof(GuiSyncContext))]
+ public class GuiSyncObject: SyncObject
+ {
+ }
+}
Added: trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/SyncContext.cs
===================================================================
--- trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/SyncContext.cs 2004-12-06 17:00:46 UTC (rev 2056)
+++ trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/SyncContext.cs 2004-12-06 20:40:45 UTC (rev 2057)
@@ -0,0 +1,188 @@
+// <file>
+// <copyright see="prj:///doc/copyright.txt"/>
+// <license see="prj:///doc/license.txt"/>
+// <owner name="Lluis Sanchez Gual" email="lluis at ximian.com"/>
+// <version value="$version"/>
+// </file>
+
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.Remoting.Contexts;
+using System.Runtime.Remoting.Messaging;
+using System.Runtime.Remoting.Activation;
+
+namespace MonoDevelop.Services
+{
+ public class SyncContext
+ {
+ [ThreadStatic]
+ static SyncContext context;
+
+ static Hashtable delegateFactories = new Hashtable ();
+ static ModuleBuilder module;
+ static AssemblyBuilder asmBuilder;
+
+ public static void SetContext (SyncContext ctx)
+ {
+ context = ctx;
+ }
+
+ public static SyncContext GetContext ()
+ {
+ return context;
+ }
+
+ public virtual void Dispatch (StatefulMessageHandler cb, object ob)
+ {
+ cb (ob);
+ }
+
+ public virtual void AsyncDispatch (StatefulMessageHandler cb, object ob)
+ {
+ cb.BeginInvoke (ob, null, null);
+ }
+
+ public Delegate CreateSynchronizedDelegate (Delegate del)
+ {
+ lock (delegateFactories.SyncRoot)
+ {
+ Type delType = del.GetType();
+ IDelegateFactory factory = delegateFactories [delType] as IDelegateFactory;
+ if (factory == null)
+ {
+ Type t = GetDelegateFactoryType (delType);
+ factory = Activator.CreateInstance (t) as IDelegateFactory;
+ delegateFactories [delType] = factory;
+ }
+ return factory.Create (del, this);
+ }
+ }
+
+ Type GetDelegateFactoryType (Type delegateType)
+ {
+ MethodInfo invoke = delegateType.GetMethod ("Invoke");
+ ModuleBuilder module = GetModuleBuilder ();
+ TypeBuilder typeBuilder = module.DefineType ("__" + delegateType.Name + "_DelegateFactory", TypeAttributes.Public, typeof(object), new Type[] {typeof(IDelegateFactory)});
+
+ // Context and target delegate field
+
+ FieldBuilder contextField = typeBuilder.DefineField ("context", typeof(SyncContext), FieldAttributes.Public);
+ FieldBuilder targetField = typeBuilder.DefineField ("target", delegateType, FieldAttributes.Public);
+
+ // Parameters
+
+ ParameterInfo[] pars = invoke.GetParameters ();
+ FieldBuilder[] paramFields = new FieldBuilder [pars.Length];
+ Type[] paramTypes = new Type[pars.Length];
+ for (int n=0; n<pars.Length; n++)
+ {
+ ParameterInfo pi = pars [n];
+ paramFields [n] = typeBuilder.DefineField ("p" + n, pi.ParameterType, FieldAttributes.Public);
+ paramTypes [n] = pi.ParameterType;
+ }
+
+ // Return value
+
+ FieldBuilder returnField = null;
+ if (invoke.ReturnType != typeof(void))
+ returnField = typeBuilder.DefineField ("ret", invoke.ReturnType, FieldAttributes.Public);
+
+ // Constructor
+
+ ConstructorBuilder ctor = typeBuilder.DefineConstructor (MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);
+ ConstructorInfo baseCtor = typeof(object).GetConstructor (Type.EmptyTypes);
+ ILGenerator gen = ctor.GetILGenerator();
+ gen.Emit (OpCodes.Ldarg_0);
+ gen.Emit (OpCodes.Call, baseCtor);
+ gen.Emit (OpCodes.Ret);
+
+ // Dispatch method
+
+ MethodBuilder methodDispatch = typeBuilder.DefineMethod ("Dispatch", MethodAttributes.Public, typeof(void), new Type[] {typeof(object)});
+ gen = methodDispatch.GetILGenerator();
+ if (returnField != null)
+ gen.Emit (OpCodes.Ldarg_0);
+ gen.Emit (OpCodes.Ldarg_0);
+ gen.Emit (OpCodes.Ldfld, targetField);
+
+ for (int n=0; n<pars.Length; n++)
+ {
+ gen.Emit (OpCodes.Ldarg_0);
+ gen.Emit (OpCodes.Ldfld, paramFields[n]);
+ }
+ gen.Emit (OpCodes.Callvirt, invoke);
+
+ if (returnField != null)
+ gen.Emit (OpCodes.Stfld, returnField);
+
+ gen.Emit (OpCodes.Ret);
+
+ // ProxyCall method
+
+ MethodBuilder methodProxyCall = typeBuilder.DefineMethod ("ProxyCall", MethodAttributes.Public, invoke.ReturnType, paramTypes);
+ gen = methodProxyCall.GetILGenerator();
+ for (int n=0; n<paramFields.Length; n++) {
+ gen.Emit (OpCodes.Ldarg_0);
+ gen.Emit (OpCodes.Ldarg, n+1);
+ gen.Emit (OpCodes.Stfld, paramFields[n]);
+ }
+ gen.Emit (OpCodes.Ldarg_0);
+ gen.Emit (OpCodes.Ldfld, contextField);
+ gen.Emit (OpCodes.Ldarg_0);
+ gen.Emit (OpCodes.Ldftn, methodDispatch);
+ gen.Emit (OpCodes.Newobj, typeof(StatefulMessageHandler).GetConstructor (new Type[] {typeof(object), typeof(IntPtr)} ));
+ gen.Emit (OpCodes.Ldnull);
+ gen.Emit (OpCodes.Callvirt, typeof(SyncContext).GetMethod ("Dispatch"));
+
+ if (returnField != null) {
+ gen.Emit (OpCodes.Ldarg_0);
+ gen.Emit (OpCodes.Ldfld, returnField);
+ }
+ gen.Emit (OpCodes.Ret);
+
+ // Create method
+
+ MethodBuilder methodCreate = typeBuilder.DefineMethod ("Create", MethodAttributes.Public, typeof(Delegate), new Type[] {typeof(Delegate), typeof(SyncContext)});
+ gen = methodCreate.GetILGenerator();
+ LocalBuilder vthis = gen.DeclareLocal (typeBuilder);
+ gen.Emit (OpCodes.Newobj, ctor);
+ gen.Emit (OpCodes.Stloc, vthis);
+ gen.Emit (OpCodes.Ldloc, vthis);
+ gen.Emit (OpCodes.Ldarg_1);
+ gen.Emit (OpCodes.Castclass, delegateType);
+ gen.Emit (OpCodes.Stfld, targetField);
+ gen.Emit (OpCodes.Ldloc, vthis);
+ gen.Emit (OpCodes.Ldarg_2);
+ gen.Emit (OpCodes.Stfld, contextField);
+ gen.Emit (OpCodes.Ldloc, vthis);
+ gen.Emit (OpCodes.Ldftn, methodProxyCall);
+ gen.Emit (OpCodes.Newobj, delegateType.GetConstructor (new Type[] {typeof(object), typeof(IntPtr)} ));
+ gen.Emit (OpCodes.Ret);
+ typeBuilder.DefineMethodOverride (methodCreate, typeof(IDelegateFactory).GetMethod ("Create"));
+
+ return typeBuilder.CreateType ();
+ }
+
+ static ModuleBuilder GetModuleBuilder ()
+ {
+ if (module == null)
+ {
+ AppDomain myDomain = System.Threading.Thread.GetDomain();
+ AssemblyName myAsmName = new AssemblyName();
+ myAsmName.Name = "MonoDevelop.DelegateGenerator.GeneratedAssembly";
+
+ asmBuilder = myDomain.DefineDynamicAssembly (myAsmName, AssemblyBuilderAccess.RunAndSave);
+ module = asmBuilder.DefineDynamicModule ("MonoDevelop.DelegateGenerator.GeneratedAssembly", "MonoDevelop.DelegateGenerator.GeneratedAssembly.dll");
+ }
+ return module;
+ }
+ }
+
+ public interface IDelegateFactory
+ {
+ Delegate Create (Delegate del, SyncContext ctx);
+ }
+}
Added: trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/SyncContextAttribute.cs
===================================================================
--- trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/SyncContextAttribute.cs 2004-12-06 17:00:46 UTC (rev 2056)
+++ trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/SyncContextAttribute.cs 2004-12-06 20:40:45 UTC (rev 2057)
@@ -0,0 +1,140 @@
+// <file>
+// <copyright see="prj:///doc/copyright.txt"/>
+// <license see="prj:///doc/license.txt"/>
+// <owner name="Lluis Sanchez Gual" email="lluis at ximian.com"/>
+// <version value="$version"/>
+// </file>
+
+
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.Remoting.Contexts;
+using System.Runtime.Remoting.Messaging;
+using System.Runtime.Remoting.Activation;
+
+namespace MonoDevelop.Services
+{
+ public class SyncContextAttribute: ContextAttribute, IContributeObjectSink
+ {
+ Type contextType;
+ SyncContext syncContext;
+
+ public SyncContextAttribute (Type contextType): base ("syncContextProperty")
+ {
+ this.contextType = contextType;
+ }
+
+ public override bool IsContextOK (Context ctx, IConstructionCallMessage msg)
+ {
+ SyncContext sctx = SyncContext.GetContext ();
+ if (sctx == null || (sctx.GetType() != contextType)) {
+ syncContext = (SyncContext) Activator.CreateInstance (contextType);
+ return false;
+ }
+ else {
+ syncContext = sctx;
+ return true;
+ }
+ }
+
+ public IMessageSink GetObjectSink (MarshalByRefObject ob, IMessageSink nextSink)
+ {
+ return new SyncContextDispatchSink (nextSink, syncContext);
+ }
+
+ public Type ConextType
+ {
+ get { return contextType; }
+ }
+ }
+
+ internal class SyncContextDispatchSink: IMessageSink
+ {
+ IMessageSink nextSink;
+ SyncContext syncContext;
+
+ class MsgData
+ {
+ public IMessage InMessage;
+ public IMessage OutMessage;
+ public IMessageSink ReplySink;
+ }
+
+ public SyncContextDispatchSink (IMessageSink nextSink, SyncContext syncContext)
+ {
+ this.nextSink = nextSink;
+ this.syncContext = syncContext;
+ }
+
+ public IMessage SyncProcessMessage (IMessage msg)
+ {
+ if (syncContext == null) return nextSink.SyncProcessMessage (msg);
+
+ IMethodMessage mm = (IMethodMessage)msg;
+ if (mm.MethodBase.IsDefined (typeof(FreeDispatchAttribute), true))
+ return nextSink.SyncProcessMessage (msg);
+
+ if (mm.MethodBase.IsDefined (typeof(AsyncDispatchAttribute), true)) {
+ AsyncProcessMessage (msg, DummySink.Instance);
+ return new ReturnMessage (null, null, 0, null, (IMethodCallMessage)mm);
+ }
+
+ MsgData md = new MsgData ();
+ md.InMessage = msg;
+ syncContext.Dispatch (new StatefulMessageHandler (DispatchMessage), md);
+ return md.OutMessage;
+ }
+
+ void DispatchMessage (object data)
+ {
+ MsgData md = (MsgData)data;
+ md.OutMessage = nextSink.SyncProcessMessage (md.InMessage);
+ }
+
+ public IMessageCtrl AsyncProcessMessage (IMessage msg, IMessageSink replySink)
+ {
+ if (syncContext == null) return nextSink.AsyncProcessMessage (msg, replySink);
+
+ MsgData md = new MsgData ();
+ md.InMessage = msg;
+ md.ReplySink = replySink;
+ syncContext.AsyncDispatch (new StatefulMessageHandler (AsyncDispatchMessage), md);
+ return null;
+ }
+
+ void AsyncDispatchMessage (object data)
+ {
+ MsgData md = (MsgData)data;
+ md.ReplySink.SyncProcessMessage (nextSink.SyncProcessMessage (md.InMessage));
+ }
+
+ public IMessageSink NextSink
+ {
+ get { return nextSink; }
+ }
+ }
+
+ internal class DummySink: IMessageSink
+ {
+ public static DummySink Instance = new DummySink();
+
+ public IMessage SyncProcessMessage (IMessage msg)
+ {
+ // Ignore
+ return null;
+ }
+
+ public IMessageCtrl AsyncProcessMessage (IMessage msg, IMessageSink replySink)
+ {
+ // Ignore
+ return null;
+ }
+
+ public IMessageSink NextSink
+ {
+ get { return null; }
+ }
+ }
+}
Added: trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/SyncObject.cs
===================================================================
--- trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/SyncObject.cs 2004-12-06 17:00:46 UTC (rev 2056)
+++ trunk/MonoDevelop/Core/src/Main/Base/Services/DispatchService/SyncObject.cs 2004-12-06 20:40:45 UTC (rev 2057)
@@ -0,0 +1,15 @@
+// <file>
+// <copyright see="prj:///doc/copyright.txt"/>
+// <license see="prj:///doc/license.txt"/>
+// <owner name="Lluis Sanchez Gual" email="lluis at ximian.com"/>
+// <version value="$version"/>
+// </file>
+
+using System;
+
+namespace MonoDevelop.Services
+{
+ public class SyncObject: ContextBoundObject
+ {
+ }
+}
More information about the Monodevelop-patches-list
mailing list