mscorlib(4.0.0.0) API with additions
SynchronizationAttribute.cs
1 using System.Collections;
5 using System.Security;
7 using System.Threading;
8 
10 {
12  [Serializable]
13  [SecurityCritical]
14  [AttributeUsage(AttributeTargets.Class)]
15  [ComVisible(true)]
16  [SecurityPermission(SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.Infrastructure)]
18  {
20  public const int NOT_SUPPORTED = 1;
21 
23  public const int SUPPORTED = 2;
24 
26  public const int REQUIRED = 4;
27 
29  public const int REQUIRES_NEW = 8;
30 
31  private const string PROPERTY_NAME = "Synchronization";
32 
33  private static readonly int _timeOut = -1;
34 
35  [NonSerialized]
36  internal AutoResetEvent _asyncWorkEvent;
37 
38  [NonSerialized]
39  private RegisteredWaitHandle _waitHandle;
40 
41  [NonSerialized]
42  internal Queue _workItemQueue;
43 
44  [NonSerialized]
45  internal bool _locked;
46 
47  internal bool _bReEntrant;
48 
49  internal int _flavor;
50 
51  [NonSerialized]
52  private SynchronizationAttribute _cliCtxAttr;
53 
54  [NonSerialized]
55  private string _syncLcid;
56 
57  [NonSerialized]
58  private ArrayList _asyncLcidList;
59 
62  public virtual bool Locked
63  {
64  get
65  {
66  return _locked;
67  }
68  set
69  {
70  _locked = value;
71  }
72  }
73 
76  public virtual bool IsReEntrant => _bReEntrant;
77 
78  internal string SyncCallOutLCID
79  {
80  get
81  {
82  return _syncLcid;
83  }
84  set
85  {
86  _syncLcid = value;
87  }
88  }
89 
90  internal ArrayList AsyncCallOutLCIDList => _asyncLcidList;
91 
92  internal bool IsKnownLCID(IMessage reqMsg)
93  {
94  string logicalCallID = ((LogicalCallContext)reqMsg.Properties[Message.CallContextKey]).RemotingData.LogicalCallID;
95  if (!logicalCallID.Equals(_syncLcid))
96  {
97  return _asyncLcidList.Contains(logicalCallID);
98  }
99  return true;
100  }
101 
104  : this(4, reEntrant: false)
105  {
106  }
107 
110  public SynchronizationAttribute(bool reEntrant)
111  : this(4, reEntrant)
112  {
113  }
114 
118  public SynchronizationAttribute(int flag)
119  : this(flag, reEntrant: false)
120  {
121  }
122 
128  public SynchronizationAttribute(int flag, bool reEntrant)
129  : base("Synchronization")
130  {
131  _bReEntrant = reEntrant;
132  switch (flag)
133  {
134  case 1:
135  case 2:
136  case 4:
137  case 8:
138  _flavor = flag;
139  break;
140  default:
141  throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "flag");
142  }
143  }
144 
145  internal void Dispose()
146  {
147  if (_waitHandle != null)
148  {
149  _waitHandle.Unregister(null);
150  }
151  }
152 
159  [SecurityCritical]
160  [ComVisible(true)]
161  public override bool IsContextOK(Context ctx, IConstructionCallMessage msg)
162  {
163  if (ctx == null)
164  {
165  throw new ArgumentNullException("ctx");
166  }
167  if (msg == null)
168  {
169  throw new ArgumentNullException("msg");
170  }
171  bool result = true;
172  if (_flavor == 8)
173  {
174  result = false;
175  }
176  else
177  {
178  SynchronizationAttribute synchronizationAttribute = (SynchronizationAttribute)ctx.GetProperty("Synchronization");
179  if ((_flavor == 1 && synchronizationAttribute != null) || (_flavor == 4 && synchronizationAttribute == null))
180  {
181  result = false;
182  }
183  if (_flavor == 4)
184  {
185  _cliCtxAttr = synchronizationAttribute;
186  }
187  }
188  return result;
189  }
190 
193  [SecurityCritical]
194  [ComVisible(true)]
196  {
197  if (_flavor != 1 && _flavor != 2 && ctorMsg != null)
198  {
199  if (_cliCtxAttr != null)
200  {
201  ctorMsg.ContextProperties.Add(_cliCtxAttr);
202  _cliCtxAttr = null;
203  }
204  else
205  {
206  ctorMsg.ContextProperties.Add(this);
207  }
208  }
209  }
210 
211  internal virtual void InitIfNecessary()
212  {
213  lock (this)
214  {
215  if (_asyncWorkEvent == null)
216  {
217  _asyncWorkEvent = new AutoResetEvent(initialState: false);
218  _workItemQueue = new Queue();
219  _asyncLcidList = new ArrayList();
220  WaitOrTimerCallback callBack = DispatcherCallBack;
221  _waitHandle = ThreadPool.RegisterWaitForSingleObject(_asyncWorkEvent, callBack, null, _timeOut, executeOnlyOnce: false);
222  }
223  }
224  }
225 
226  private void DispatcherCallBack(object stateIgnored, bool ignored)
227  {
228  WorkItem work;
229  lock (_workItemQueue)
230  {
231  work = (WorkItem)_workItemQueue.Dequeue();
232  }
233  ExecuteWorkItem(work);
234  HandleWorkCompletion();
235  }
236 
237  internal virtual void HandleThreadExit()
238  {
239  HandleWorkCompletion();
240  }
241 
242  internal virtual void HandleThreadReEntry()
243  {
244  WorkItem workItem = new WorkItem(null, null, null);
245  workItem.SetDummy();
246  HandleWorkRequest(workItem);
247  }
248 
249  internal virtual void HandleWorkCompletion()
250  {
251  WorkItem workItem = null;
252  bool flag = false;
253  lock (_workItemQueue)
254  {
255  if (_workItemQueue.Count >= 1)
256  {
257  workItem = (WorkItem)_workItemQueue.Peek();
258  flag = true;
259  workItem.SetSignaled();
260  }
261  else
262  {
263  _locked = false;
264  }
265  }
266  if (flag)
267  {
268  if (workItem.IsAsync())
269  {
270  _asyncWorkEvent.Set();
271  }
272  else
273  {
274  lock (workItem)
275  {
276  Monitor.Pulse(workItem);
277  }
278  }
279  }
280  }
281 
282  internal virtual void HandleWorkRequest(WorkItem work)
283  {
284  if (!IsNestedCall(work._reqMsg))
285  {
286  if (work.IsAsync())
287  {
288  bool flag = true;
289  lock (_workItemQueue)
290  {
291  work.SetWaiting();
292  _workItemQueue.Enqueue(work);
293  if (!_locked && _workItemQueue.Count == 1)
294  {
295  work.SetSignaled();
296  _locked = true;
297  _asyncWorkEvent.Set();
298  }
299  }
300  }
301  else
302  {
303  lock (work)
304  {
305  bool flag;
306  lock (_workItemQueue)
307  {
308  if (!_locked && _workItemQueue.Count == 0)
309  {
310  _locked = true;
311  flag = false;
312  }
313  else
314  {
315  flag = true;
316  work.SetWaiting();
317  _workItemQueue.Enqueue(work);
318  }
319  }
320  if (flag)
321  {
322  Monitor.Wait(work);
323  if (!work.IsDummy())
324  {
325  DispatcherCallBack(null, ignored: true);
326  }
327  else
328  {
329  lock (_workItemQueue)
330  {
331  _workItemQueue.Dequeue();
332  }
333  }
334  }
335  else if (!work.IsDummy())
336  {
337  work.SetSignaled();
338  ExecuteWorkItem(work);
339  HandleWorkCompletion();
340  }
341  }
342  }
343  }
344  else
345  {
346  work.SetSignaled();
347  work.Execute();
348  }
349  }
350 
351  internal void ExecuteWorkItem(WorkItem work)
352  {
353  work.Execute();
354  }
355 
356  internal bool IsNestedCall(IMessage reqMsg)
357  {
358  bool flag = false;
359  if (!IsReEntrant)
360  {
361  string syncCallOutLCID = SyncCallOutLCID;
362  if (syncCallOutLCID != null)
363  {
364  LogicalCallContext logicalCallContext = (LogicalCallContext)reqMsg.Properties[Message.CallContextKey];
365  if (logicalCallContext != null && syncCallOutLCID.Equals(logicalCallContext.RemotingData.LogicalCallID))
366  {
367  flag = true;
368  }
369  }
370  if (!flag && AsyncCallOutLCIDList.Count > 0)
371  {
372  LogicalCallContext logicalCallContext2 = (LogicalCallContext)reqMsg.Properties[Message.CallContextKey];
373  if (AsyncCallOutLCIDList.Contains(logicalCallContext2.RemotingData.LogicalCallID))
374  {
375  flag = true;
376  }
377  }
378  }
379  return flag;
380  }
381 
385  [SecurityCritical]
387  {
388  InitIfNecessary();
389  return new SynchronizedServerContextSink(this, nextSink);
390  }
391 
395  [SecurityCritical]
397  {
398  InitIfNecessary();
399  return new SynchronizedClientContextSink(this, nextSink);
400  }
401  }
402 }
The exception that is thrown when a null reference (Nothing in Visual Basic) is passed to a method th...
Describes a set of security permissions applied to code. This class cannot be inherited.
Represents a handle that has been registered when calling M:System.Threading.ThreadPool....
override void GetPropertiesForNewContext(IConstructionCallMessage ctorMsg)
Adds the Synchronized context property to the specified T:System.Runtime.Remoting....
const int REQUIRED
Indicates that the class to which this attribute is applied must be created in a context that has syn...
Represents the construction call request of an object.
bool Set()
Sets the state of the event to signaled, allowing one or more waiting threads to proceed.
virtual int Count
Gets the number of elements actually contained in the T:System.Collections.ArrayList.
Definition: ArrayList.cs:2255
SynchronizationAttribute(int flag, bool reEntrant)
Initializes a new instance of the T:System.Runtime.Remoting.Contexts.SynchronizationAttribute class w...
Definition: __Canon.cs:3
Provides a mechanism that synchronizes access to objects.
Definition: Monitor.cs:13
static bool Wait(object obj, int millisecondsTimeout, bool exitContext)
Releases the lock on an object and blocks the current thread until it reacquires the lock....
Definition: Monitor.cs:201
SynchronizationAttribute(int flag)
Initializes a new instance of the T:System.Runtime.Remoting.Contexts.SynchronizationAttribute class w...
virtual object Peek()
Returns the object at the beginning of the T:System.Collections.Queue without removing it.
Definition: Queue.cs:451
virtual void Enqueue(object obj)
Adds an object to the end of the T:System.Collections.Queue.
Definition: Queue.cs:407
Defines an environment for the objects that are resident inside it and for which a policy can be enfo...
Definition: Context.cs:14
virtual IMessageSink GetServerContextSink(IMessageSink nextSink)
Creates a synchronized dispatch sink and chains it in front of the provided chain of sinks at the con...
IDictionary Properties
Gets an T:System.Collections.IDictionary that represents a collection of the message's properties.
Definition: IMessage.cs:15
const int NOT_SUPPORTED
Indicates that the class to which this attribute is applied cannot be created in a context that has s...
virtual bool IsReEntrant
Gets or sets a Boolean value indicating whether reentry is required.
SecurityAction
Specifies the security actions that can be performed using declarative security.
Provides information about, and means to manipulate, the current environment and platform....
Definition: Environment.cs:21
static RegisteredWaitHandle RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, object state, uint millisecondsTimeOutInterval, bool executeOnlyOnce)
Registers a delegate to wait for a T:System.Threading.WaitHandle, specifying a 32-bit unsigned intege...
Definition: ThreadPool.cs:82
virtual bool Contains(object item)
Determines whether an element is in the T:System.Collections.ArrayList.
Definition: ArrayList.cs:2486
Contributes an interception sink at the context boundary on the client end of a remoting call.
virtual int Count
Gets the number of elements contained in the T:System.Collections.Queue.
Definition: Queue.cs:250
Notifies a waiting thread that an event has occurred. This class cannot be inherited.
SynchronizationAttribute(bool reEntrant)
Initializes a new instance of the T:System.Runtime.Remoting.Contexts.SynchronizationAttribute class w...
delegate void WaitOrTimerCallback(object state, bool timedOut)
Represents a method to be called when a T:System.Threading.WaitHandle is signaled or times out.
virtual IContextProperty GetProperty(string name)
Returns a specific context property, specified by name.
Definition: Context.cs:226
Represents a first-in, first-out collection of objects.
Definition: Queue.cs:13
int Add(object value)
Adds an item to the T:System.Collections.IList.
override bool IsContextOK(Context ctx, IConstructionCallMessage msg)
Returns a Boolean value indicating whether the context parameter meets the context attribute's requir...
Indicates that data in the pipe is transmitted and read as a stream of messages.
Provides a set of properties that are carried with the execution code path during remote method calls...
const int REQUIRES_NEW
Indicates that the class to which this attribute is applied must be created in a context with a new i...
SynchronizationAttribute()
Initializes a new instance of the T:System.Runtime.Remoting.Contexts.SynchronizationAttribute class w...
AttributeTargets
Specifies the application elements on which it is valid to apply an attribute.
Contains communication data sent between cooperating message sinks.
Definition: IMessage.cs:9
const int SUPPORTED
Indicates that the class to which this attribute is applied is not dependent on whether the context h...
The exception that is thrown when one of the arguments provided to a method is not valid.
static void Pulse(object obj)
Notifies a thread in the waiting queue of a change in the locked object's state.
Definition: Monitor.cs:280
Defines the interface for a message sink.
Definition: IMessageSink.cs:8
Specifies that the class can be serialized.
virtual IMessageSink GetClientContextSink(IMessageSink nextSink)
Creates a CallOut sink and chains it in front of the provided chain of sinks at the context boundary ...
Contributes an interception sink at the context boundary on the server end of a remoting call.
SecurityPermissionFlag
Specifies access flags for the security permission object.
virtual bool Locked
Gets or sets a Boolean value indicating whether the T:System.Runtime.Remoting.Contexts....
virtual object Dequeue()
Removes and returns the object at the beginning of the T:System.Collections.Queue.
Definition: Queue.cs:434
Provides the default implementations of the T:System.Runtime.Remoting.Contexts.IContextAttribute and ...
Enforces a synchronization domain for the current context and all contexts that share the same instan...
IList ContextProperties
Gets a list of context properties that define the context in which the object is to be created.
Provides a pool of threads that can be used to execute tasks, post work items, process asynchronous I...
Definition: ThreadPool.cs:14
bool Unregister(WaitHandle waitObject)
Cancels a registered wait operation issued by the M:System.Threading.ThreadPool.RegisterWaitForSingle...
Implements the T:System.Collections.IList interface using an array whose size is dynamically increase...
Definition: ArrayList.cs:14