We need you! We're working hard on the next version of Developer Fusion -
Let us know what you think we should be up to!
- namespace System.Runtime.Remoting.Contexts
- {
- using System.Threading;
- using System.Runtime.Remoting;
- using System.Runtime.Remoting.Messaging;
- using System.Runtime.Remoting.Activation;
- using System.Security.Permissions;
- using System;
- using Queue = System.Collections.Queue;
- using ArrayList = System.Collections.ArrayList;
- [Serializable()]
- [AttributeUsage(AttributeTargets.Class)]
- [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
- [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.Infrastructure)]
- [System.Runtime.InteropServices.ComVisible(true)]
- public class SynchronizationAttribute : ContextAttribute, IContributeServerContextSink, IContributeClientContextSink
- {
-
- public const int NOT_SUPPORTED = 1;
-
-
- public const int SUPPORTED = 2;
-
-
- public const int REQUIRED = 4;
-
-
-
- public const int REQUIRES_NEW = 8;
-
- private const string PROPERTY_NAME = "Synchronization";
-
- private static readonly UInt32 _timeOut = (UInt32)2147483647;
-
- [NonSerialized()]
- internal AutoResetEvent _asyncWorkEvent;
- [NonSerialized()]
- private RegisteredWaitHandle _waitHandle;
-
-
- [NonSerialized()]
- internal Queue _workItemQueue;
-
- [NonSerialized()]
- internal bool _locked;
-
- internal bool _bReEntrant;
-
- internal int _flavor;
-
- [NonSerialized()]
- private SynchronizationAttribute _cliCtxAttr;
-
- [NonSerialized()]
- private string _syncLcid;
- [NonSerialized()]
- private ArrayList _asyncLcidList;
-
-
- public virtual bool Locked {
- get { return _locked; }
- set { _locked = value; }
- }
- public virtual bool IsReEntrant {
- get { return _bReEntrant; }
- }
-
- internal string SyncCallOutLCID {
- get {
- BCLDebug.Assert(!_bReEntrant, "Should not use this for the reentrant case");
-
- return _syncLcid;
- }
-
- set {
- BCLDebug.Assert(!_bReEntrant, "Should not use this for the reentrant case");
-
- BCLDebug.Assert(_syncLcid == null || (_syncLcid != null && value == null) || _syncLcid.Equals(value), "context can be associated with one logical call at a time");
-
- _syncLcid = value;
- }
- }
-
- internal ArrayList AsyncCallOutLCIDList {
- get { return _asyncLcidList; }
- }
-
- internal bool IsKnownLCID(IMessage reqMsg)
- {
- string msgLCID = ((LogicalCallContext)reqMsg.Properties[Message.CallContextKey]).RemotingData.LogicalCallID;
- return (msgLCID.Equals(_syncLcid) || _asyncLcidList.Contains(msgLCID));
-
- }
-
-
-
-
- public SynchronizationAttribute() : this(REQUIRED, false)
- {
- }
-
-
-
- public SynchronizationAttribute(bool reEntrant) : this(REQUIRED, reEntrant)
- {
- }
-
-
- public SynchronizationAttribute(int flag) : this(flag, false)
- {
- }
-
-
-
- public SynchronizationAttribute(int flag, bool reEntrant) : base(PROPERTY_NAME)
- {
-
- _bReEntrant = reEntrant;
-
- switch (flag) {
- case NOT_SUPPORTED:
- case SUPPORTED:
- case REQUIRED:
- case REQUIRES_NEW:
- _flavor = flag;
- break;
- default:
- throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "flag");
- break;
- }
- }
-
-
- internal void Dispose()
- {
-
- if (_waitHandle != null)
- _waitHandle.Unregister(null);
- }
-
-
- [System.Runtime.InteropServices.ComVisible(true)]
- public override bool IsContextOK(Context ctx, IConstructionCallMessage msg)
- {
- if (ctx == null)
- throw new ArgumentNullException("ctx");
- if (msg == null)
- throw new ArgumentNullException("msg");
-
-
- bool isOK = true;
- if (_flavor == REQUIRES_NEW) {
- isOK = false;
-
-
- BCLDebug.Assert(ctx.GetProperty(PROPERTY_NAME) != this, "ctx.GetProperty(PROPERTY_NAME) != this");
- }
- else {
- SynchronizationAttribute syncProp = (SynchronizationAttribute)ctx.GetProperty(PROPERTY_NAME);
- if (((_flavor == NOT_SUPPORTED) && (syncProp != null)) || ((_flavor == REQUIRED) && (syncProp == null))) {
- isOK = false;
- }
-
- if (_flavor == REQUIRED) {
-
- _cliCtxAttr = syncProp;
- }
- }
- return isOK;
- }
-
-
- [System.Runtime.InteropServices.ComVisible(true)]
- public override void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
- {
- if ((_flavor == NOT_SUPPORTED) || (_flavor == SUPPORTED) || (null == ctorMsg)) {
- return;
- }
-
- if (_cliCtxAttr != null) {
- BCLDebug.Assert(_flavor == REQUIRED, "Use cli-ctx property only for the REQUIRED flavor");
- ctorMsg.ContextProperties.Add((IContextProperty)_cliCtxAttr);
- _cliCtxAttr = null;
- }
- else {
- ctorMsg.ContextProperties.Add((IContextProperty)this);
- }
- }
-
-
-
-
- internal virtual void InitIfNecessary()
- {
- lock (this) {
- if (_asyncWorkEvent == null) {
-
- _asyncWorkEvent = new AutoResetEvent(false);
-
- _workItemQueue = new Queue();
- _asyncLcidList = new ArrayList();
-
- WaitOrTimerCallback callBackDelegate = new WaitOrTimerCallback(this.DispatcherCallBack);
-
-
-
-
- _waitHandle = ThreadPool.RegisterWaitForSingleObject(_asyncWorkEvent, callBackDelegate, null, _timeOut, false);
-
- }
- }
- }
-
-
- private void DispatcherCallBack(object stateIgnored, bool ignored)
- {
-
-
-
-
-
-
- BCLDebug.Assert(_locked == true, "_locked==true");
- WorkItem work;
-
- lock (_workItemQueue) {
- work = (WorkItem)_workItemQueue.Dequeue();
-
- }
- BCLDebug.Assert(work != null, "work!=null");
- BCLDebug.Assert(work.IsSignaled() && !(work.IsDummy()), "work.IsSignaled() && !(work.IsDummy())");
-
- ExecuteWorkItem(work);
- HandleWorkCompletion();
-
- }
-
-
- internal virtual void HandleThreadExit()
- {
-
-
- BCLDebug.Assert(_locked == true, "_locked==true");
- HandleWorkCompletion();
- }
-
-
- internal virtual void HandleThreadReEntry()
- {
-
-
- WorkItem work = new WorkItem(null, null, null);
- work.SetDummy();
- HandleWorkRequest(work);
- }
-
-
- internal virtual void HandleWorkCompletion()
- {
-
- BCLDebug.Assert(_locked == true, "_locked==true");
-
- WorkItem nextWork = null;
- bool bNotify = false;
- lock (_workItemQueue) {
- if (_workItemQueue.Count >= 1) {
- nextWork = (WorkItem)_workItemQueue.Peek();
- bNotify = true;
- nextWork.SetSignaled();
- }
- else {
-
-
-
-
- _locked = false;
- }
- }
-
- if (bNotify) {
-
-
- if (nextWork.IsAsync()) {
-
- _asyncWorkEvent.Set();
-
- }
- else {
-
- lock (nextWork) {
- Monitor.Pulse(nextWork);
-
- }
- }
- }
- }
-
-
- internal virtual void HandleWorkRequest(WorkItem work)
- {
- bool bQueued;
-
-
- if (!IsNestedCall(work._reqMsg)) {
-
- if (work.IsAsync()) {
-
- bQueued = true;
-
- lock (_workItemQueue) {
-
- work.SetWaiting();
- _workItemQueue.Enqueue(work);
-
-
- if ((!_locked) && (_workItemQueue.Count == 1)) {
-
- work.SetSignaled();
-
- _locked = true;
- _asyncWorkEvent.Set();
- }
- }
- }
- else {
-
-
- lock (work) {
-
- lock (_workItemQueue) {
- if ((!_locked) && (_workItemQueue.Count == 0)) {
- _locked = true;
-
- bQueued = false;
- }
- else {
-
- bQueued = true;
- work.SetWaiting();
- _workItemQueue.Enqueue(work);
- }
- }
-
- if (bQueued == true) {
-
-
-
-
- Monitor.Wait(work);
-
- BCLDebug.Assert(_locked == true, "_locked==true");
-
-
- if (!work.IsDummy()) {
-
-
-
- DispatcherCallBack(null, true);
- }
- else {
-
-
- lock (_workItemQueue) {
- _workItemQueue.Dequeue();
- }
-
-
-
- }
- }
- else {
-
- if (!work.IsDummy()) {
-
-
- BCLDebug.Assert(_locked == true, "_locked==true");
- work.SetSignaled();
- ExecuteWorkItem(work);
-
- HandleWorkCompletion();
- }
- }
- }
- }
- }
- else {
-
-
-
-
- BCLDebug.Assert(_locked == true, "_locked==true");
- work.SetSignaled();
- work.Execute();
-
-
-
- }
- }
-
- internal void ExecuteWorkItem(WorkItem work)
- {
- work.Execute();
- }
-
- internal bool IsNestedCall(IMessage reqMsg)
- {
-
-
-
-
-
-
-
- bool bNested = false;
- if (!IsReEntrant) {
- string lcid = SyncCallOutLCID;
- if (lcid != null) {
-
- LogicalCallContext callCtx = (LogicalCallContext)reqMsg.Properties[Message.CallContextKey];
-
- if (callCtx != null && lcid.Equals(callCtx.RemotingData.LogicalCallID)) {
-
-
-
- bNested = true;
- }
- }
- if (!bNested && AsyncCallOutLCIDList.Count > 0) {
-
- LogicalCallContext callCtx = (LogicalCallContext)reqMsg.Properties[Message.CallContextKey];
- if (AsyncCallOutLCIDList.Contains(callCtx.RemotingData.LogicalCallID)) {
- bNested = true;
- }
- }
- }
- return bNested;
- }
-
-
-
- public virtual IMessageSink GetServerContextSink(IMessageSink nextSink)
- {
- InitIfNecessary();
-
- SynchronizedServerContextSink propertySink = new SynchronizedServerContextSink(this, nextSink);
-
- return (IMessageSink)propertySink;
- }
-
-
- public virtual IMessageSink GetClientContextSink(IMessageSink nextSink)
- {
- InitIfNecessary();
-
- SynchronizedClientContextSink propertySink = new SynchronizedClientContextSink(this, nextSink);
-
- return (IMessageSink)propertySink;
- }
-
- }
-
-
-
- internal class SynchronizedServerContextSink : InternalSink, IMessageSink
- {
- internal IMessageSink _nextSink;
- internal SynchronizationAttribute _property;
-
- internal SynchronizedServerContextSink(SynchronizationAttribute prop, IMessageSink nextSink)
- {
- _property = prop;
- _nextSink = nextSink;
- }
-
- ~SynchronizedServerContextSink()
- {
- _property.Dispose();
- }
-
-
- public virtual IMessage SyncProcessMessage(IMessage reqMsg)
- {
-
- WorkItem work = new WorkItem(reqMsg, _nextSink, null);
-
-
-
-
- _property.HandleWorkRequest(work);
-
-
- return work.ReplyMessage;
- }
-
-
- public virtual IMessageCtrl AsyncProcessMessage(IMessage reqMsg, IMessageSink replySink)
- {
-
- WorkItem work = new WorkItem(reqMsg, _nextSink, replySink);
- work.SetAsync();
-
- _property.HandleWorkRequest(work);
-
- return null;
- }
-
-
- public IMessageSink NextSink {
- get { return _nextSink; }
- }
- }
-
-
-
- internal class WorkItem
- {
- private const int FLG_WAITING = 1;
- private const int FLG_SIGNALED = 2;
- private const int FLG_ASYNC = 4;
- private const int FLG_DUMMY = 8;
-
- internal int _flags;
- internal IMessage _reqMsg;
- internal IMessageSink _nextSink;
-
- internal IMessageSink _replySink;
-
- internal IMessage _replyMsg;
-
-
- internal Context _ctx;
-
- internal LogicalCallContext _callCtx;
- static internal InternalCrossContextDelegate _xctxDel = new InternalCrossContextDelegate(ExecuteCallback);
-
-
-
-
- internal WorkItem(IMessage reqMsg, IMessageSink nextSink, IMessageSink replySink)
- {
- _reqMsg = reqMsg;
- _replyMsg = null;
- _nextSink = nextSink;
- _replySink = replySink;
- _ctx = Thread.CurrentContext;
- _callCtx = CallContext.GetLogicalCallContext();
-
-
- }
-
-
- internal virtual void SetWaiting()
- {
- BCLDebug.Assert(!IsWaiting(), "!IsWaiting()");
- _flags |= FLG_WAITING;
- }
-
- internal virtual bool IsWaiting()
- {
- return (_flags & FLG_WAITING) == FLG_WAITING;
- }
-
-
- internal virtual void SetSignaled()
- {
- BCLDebug.Assert(!IsSignaled(), "!IsSignaled()");
- _flags |= FLG_SIGNALED;
- }
-
- internal virtual bool IsSignaled()
- {
- return (_flags & FLG_SIGNALED) == FLG_SIGNALED;
- }
-
- internal virtual void SetAsync()
- {
- _flags |= FLG_ASYNC;
- }
-
- internal virtual bool IsAsync()
- {
- return (_flags & FLG_ASYNC) == FLG_ASYNC;
- }
-
- internal virtual void SetDummy()
- {
- _flags |= FLG_DUMMY;
- }
-
- internal virtual bool IsDummy()
- {
- return (_flags & FLG_DUMMY) == FLG_DUMMY;
- }
-
-
- static internal object ExecuteCallback(object[] args)
- {
- WorkItem This = (WorkItem)args[0];
-
- if (This.IsAsync()) {
-
- This._nextSink.AsyncProcessMessage(This._reqMsg, This._replySink);
- }
- else if (This._nextSink != null) {
-
- This._replyMsg = This._nextSink.SyncProcessMessage(This._reqMsg);
- }
- return null;
- }
-
-
- internal virtual void Execute()
- {
-
-
- BCLDebug.Assert(IsSignaled(), "IsSignaled()");
-
- Thread.CurrentThread.InternalCrossContextCallback(_ctx, _xctxDel, new object[] {this});
- }
- internal virtual IMessage ReplyMessage {
- get { return _replyMsg; }
- }
- }
-
-
-
-
- internal class SynchronizedClientContextSink : InternalSink, IMessageSink
- {
- internal IMessageSink _nextSink;
- internal SynchronizationAttribute _property;
-
- internal SynchronizedClientContextSink(SynchronizationAttribute prop, IMessageSink nextSink)
- {
- _property = prop;
- _nextSink = nextSink;
- }
-
- ~SynchronizedClientContextSink()
- {
- _property.Dispose();
- }
-
-
- public virtual IMessage SyncProcessMessage(IMessage reqMsg)
- {
- BCLDebug.Assert(_property.Locked == true, "_property.Locked == true");
- IMessage replyMsg;
- if (_property.IsReEntrant) {
-
-
-
- _property.HandleThreadExit();
-
-
- replyMsg = _nextSink.SyncProcessMessage(reqMsg);
-
-
-
-
-
- _property.HandleThreadReEntry();
- BCLDebug.Assert(_property.Locked == true, "_property.Locked == true");
- }
- else {
-
-
-
- LogicalCallContext cctx = (LogicalCallContext)reqMsg.Properties[Message.CallContextKey];
-
- string lcid = cctx.RemotingData.LogicalCallID;
- bool bClear = false;
- if (lcid == null) {
-
-
-
-
-
-
-
- lcid = Identity.GetNewLogicalCallID();
- cctx.RemotingData.LogicalCallID = lcid;
- bClear = true;
-
- BCLDebug.Assert(_property.SyncCallOutLCID == null, "Synchronization domain is already in a callOut state");
- }
-
- bool bTopLevel = false;
- if (_property.SyncCallOutLCID == null) {
- _property.SyncCallOutLCID = lcid;
- bTopLevel = true;
- }
-
- BCLDebug.Assert(lcid.Equals(_property.SyncCallOutLCID), "Bad synchronization domain state!");
-
- replyMsg = _nextSink.SyncProcessMessage(reqMsg);
-
-
- if (bTopLevel) {
- _property.SyncCallOutLCID = null;
-
-
-
-
- if (bClear) {
-
-
-
-
- LogicalCallContext cctxRet = (LogicalCallContext)replyMsg.Properties[Message.CallContextKey];
- BCLDebug.Assert(cctxRet != null, "CallContext should be non-null");
- cctxRet.RemotingData.LogicalCallID = null;
- }
- }
-
-
- }
- return replyMsg;
- }
-
-
- public virtual IMessageCtrl AsyncProcessMessage(IMessage reqMsg, IMessageSink replySink)
- {
- IMessageCtrl msgCtrl = null;
-
- BCLDebug.Assert(_property.Locked == true, "_property.Locked == true");
-
- if (!_property.IsReEntrant) {
-
-
-
-
- LogicalCallContext cctx = (LogicalCallContext)reqMsg.Properties[Message.CallContextKey];
-
-
-
-
-
-
-
- &nb