The Labs \ Source Viewer \ SSCLI \ System.Threading \ SynchronizationContextProperties

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. /*============================================================
  15. **
  16. ** Class:  SynchronizationContext
  17. **
  18. **
  19. ** Purpose: Capture synchronization semantics for asynchronous callbacks
  20. **
  21. **
  22. ===========================================================*/
  23. namespace System.Threading
  24. {
  25.     using Microsoft.Win32.SafeHandles;
  26.     using System.Security.Permissions;
  27.     using System.Runtime.InteropServices;
  28.     using System.Runtime.CompilerServices;
  29.     using System.Runtime.ConstrainedExecution;
  30.     using System.Reflection;
  31.    
  32.    
  33.     internal struct SynchronizationContextSwitcher : IDisposable
  34.     {
  35.         internal SynchronizationContext savedSC;
  36.         internal SynchronizationContext currSC;
  37.         internal ExecutionContext _ec;
  38.        
  39.         public override bool Equals(object obj)
  40.         {
  41.             if (obj == null || !(obj is SynchronizationContextSwitcher))
  42.                 return false;
  43.             SynchronizationContextSwitcher sw = (SynchronizationContextSwitcher)obj;
  44.             return (this.savedSC == sw.savedSC && this.currSC == sw.currSC && this._ec == sw._ec);
  45.         }
  46.        
  47.         public override int GetHashCode()
  48.         {
  49.             return ToString().GetHashCode();
  50.         }
  51.        
  52.         public static bool operator ==(SynchronizationContextSwitcher c1, SynchronizationContextSwitcher c2)
  53.         {
  54.             return c1.Equals(c2);
  55.         }
  56.        
  57.         public static bool operator !=(SynchronizationContextSwitcher c1, SynchronizationContextSwitcher c2)
  58.         {
  59.             return !c1.Equals(c2);
  60.         }
  61.        
  62.        
  63.        
  64.        
  65.         /// <internalonly/>
  66.         void IDisposable.Dispose()
  67.         {
  68.             Undo();
  69.         }
  70.        
  71.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
  72.         internal bool UndoNoThrow()
  73.         {
  74.             if (_ec == null) {
  75.                 return true;
  76.             }
  77.            
  78.             try {
  79.                 Undo();
  80.             }
  81.             catch {
  82.                 return false;
  83.             }
  84.             return true;
  85.         }
  86.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
  87.         public void Undo()
  88.         {
  89.             if (_ec == null) {
  90.                 return;
  91.             }
  92.            
  93.             ExecutionContext executionContext = Thread.CurrentThread.GetExecutionContextNoCreate();
  94.             if (_ec != executionContext) {
  95.                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SwitcherCtxMismatch"));
  96.             }
  97.             if (currSC != _ec.SynchronizationContext) {
  98.                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SwitcherCtxMismatch"));
  99.             }
  100.             BCLDebug.Assert(executionContext != null, " ExecutionContext can't be null");
  101.             // restore the Saved Sync context as current
  102.             executionContext.SynchronizationContext = savedSC;
  103.             // can't reuse this anymore
  104.             _ec = null;
  105.         }
  106.     }
  107.    
  108.    
  109.     public delegate void SendOrPostCallback(object state);
  110.    
  111.     [Flags()]
  112.     enum SynchronizationContextProperties
  113.     {
  114.         None = 0,
  115.         RequireWaitNotification = 1
  116.     }
  117.    
  118.     [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.ControlPolicy | SecurityPermissionFlag.ControlEvidence)]
  119.     public class SynchronizationContext
  120.     {
  121.         SynchronizationContextProperties _props = SynchronizationContextProperties.None;
  122.        
  123.         public SynchronizationContext()
  124.         {
  125.         }
  126.        
  127.        
  128.         // protected so that only the derived sync context class can enable these flags
  129.         protected void SetWaitNotificationRequired()
  130.         {
  131.             // Prepare the method so that it can be called in a reliable fashion when a wait is needed.
  132.             // This will obviously only make the Wait reliable if the Wait method is itself reliable. The only thing
  133.             // preparing the method here does is to ensure there is no failure point before the method execution begins.
  134.            
  135.             RuntimeHelpers.PrepareDelegate(new WaitDelegate(this.Wait));
  136.             _props |= SynchronizationContextProperties.RequireWaitNotification;
  137.         }
  138.        
  139.         public bool IsWaitNotificationRequired()
  140.         {
  141.             return ((_props & SynchronizationContextProperties.RequireWaitNotification) != 0);
  142.         }
  143.        
  144.        
  145.        
  146.         public virtual void Send(SendOrPostCallback d, object state)
  147.         {
  148.             d(state);
  149.         }
  150.        
  151.         public virtual void Post(SendOrPostCallback d, object state)
  152.         {
  153.             ThreadPool.QueueUserWorkItem(new WaitCallback(d), state);
  154.         }
  155.        
  156.        
  157.         /// <summary>
  158.         /// Optional override for subclasses, for responding to notification that operation is starting.
  159.         /// </summary>
  160.         public virtual void OperationStarted()
  161.         {
  162.         }
  163.        
  164.         /// <summary>
  165.         /// Optional override for subclasses, for responding to notification that operation has completed.
  166.         /// </summary>
  167.         public virtual void OperationCompleted()
  168.         {
  169.         }
  170.        
  171.         // Method called when the CLR does a wait operation
  172.         [CLSCompliant(false)]
  173.         [PrePrepareMethod()]
  174.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlPolicy | SecurityPermissionFlag.ControlEvidence)]
  175.         public virtual int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
  176.         {
  177.             return WaitHelper(waitHandles, waitAll, millisecondsTimeout);
  178.         }
  179.        
  180.         // Static helper to which the above method can delegate to in order to get the default
  181.         // COM behavior.
  182.         [CLSCompliant(false)]
  183.         [PrePrepareMethod()]
  184.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  185.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlPolicy | SecurityPermissionFlag.ControlEvidence), ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
  186.         protected static extern int WaitHelper(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout);
  187.        
  188.         // set SynchronizationContext on the current thread
  189.         [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.ControlPolicy | SecurityPermissionFlag.ControlEvidence)]
  190.         public static void SetSynchronizationContext(SynchronizationContext syncContext)
  191.         {
  192.             SetSynchronizationContext(syncContext, Thread.CurrentThread.ExecutionContext.SynchronizationContext);
  193.         }
  194.        
  195.         static internal SynchronizationContextSwitcher SetSynchronizationContext(SynchronizationContext syncContext, SynchronizationContext prevSyncContext)
  196.         {
  197.             // get current execution context
  198.             ExecutionContext ec = Thread.CurrentThread.ExecutionContext;
  199.             // create a swticher
  200.             SynchronizationContextSwitcher scsw = new SynchronizationContextSwitcher();
  201.            
  202.             RuntimeHelpers.PrepareConstrainedRegions();
  203.             try {
  204.                 // attach the switcher to the exec context
  205.                 scsw._ec = ec;
  206.                 // save the current sync context using the passed in value
  207.                 scsw.savedSC = prevSyncContext;
  208.                 // save the new sync context also
  209.                 scsw.currSC = syncContext;
  210.                 // update the current sync context to the new context
  211.                 ec.SynchronizationContext = syncContext;
  212.             }
  213.             catch {
  214.                 // Any exception means we just restore the old SyncCtx
  215.                 scsw.UndoNoThrow();
  216.                 //No exception will be thrown in this Undo()
  217.                 throw;
  218.             }
  219.             // return switcher
  220.             return scsw;
  221.         }
  222.        
  223.         // Get the current SynchronizationContext on the current thread
  224.         public static SynchronizationContext Current {
  225.             get {
  226.                 ExecutionContext ec = Thread.CurrentThread.GetExecutionContextNoCreate();
  227.                 if (ec != null)
  228.                     return ec.SynchronizationContext;
  229.                 return null;
  230.             }
  231.         }
  232.        
  233.         // helper to Clone this SynchronizationContext,
  234.         public virtual SynchronizationContext CreateCopy()
  235.         {
  236.             // the CLR dummy has an empty clone function - no member data
  237.             return new SynchronizationContext();
  238.         }
  239.        
  240.         private static int InvokeWaitMethodHelper(SynchronizationContext syncContext, IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
  241.         {
  242.             return syncContext.Wait(waitHandles, waitAll, millisecondsTimeout);
  243.         }
  244.     }
  245. }

Developer Fusion