Implement MachineKey.Protect and MachineKey.Unprotect
[mono.git] / mcs / class / System.Web.Mvc2 / System.Web.Mvc / Async / TriggerListener.cs
1 /* ****************************************************************************\r
2  *\r
3  * Copyright (c) Microsoft Corporation. All rights reserved.\r
4  *\r
5  * This software is subject to the Microsoft Public License (Ms-PL). \r
6  * A copy of the license can be found in the license.htm file included \r
7  * in this distribution.\r
8  *\r
9  * You must not remove this notice, or any other, from this software.\r
10  *\r
11  * ***************************************************************************/\r
12 \r
13 namespace System.Web.Mvc.Async {\r
14     using System;\r
15     using System.Threading;\r
16 \r
17     // This class is used to wait for triggers and a continuation. When the continuation has been provded\r
18     // and all triggers have been fired, the continuation is called. Similar to WaitHandle.WaitAll().\r
19     // New instances of this type are initially in the inactive state; activation is enabled by a call\r
20     // to Activate().\r
21 \r
22     // This class is thread-safe.\r
23 \r
24     internal sealed class TriggerListener {\r
25 \r
26         private readonly Trigger _activateTrigger;\r
27         private volatile Action _continuation;\r
28         private readonly SingleEntryGate _continuationFiredGate = new SingleEntryGate();\r
29         private int _outstandingTriggers;\r
30         private readonly Trigger _setContinuationTrigger;\r
31 \r
32         public TriggerListener() {\r
33             _activateTrigger = CreateTrigger();\r
34             _setContinuationTrigger = CreateTrigger();\r
35         }\r
36 \r
37         public void Activate() {\r
38             _activateTrigger.Fire();\r
39         }\r
40 \r
41         public Trigger CreateTrigger() {\r
42             Interlocked.Increment(ref _outstandingTriggers);\r
43 \r
44             SingleEntryGate triggerFiredGate = new SingleEntryGate();\r
45             return new Trigger(() => {\r
46                 if (triggerFiredGate.TryEnter()) {\r
47                     HandleTriggerFired();\r
48                 }\r
49             });\r
50         }\r
51 \r
52         private void HandleTriggerFired() {\r
53             if (Interlocked.Decrement(ref _outstandingTriggers) == 0) {\r
54                 if (_continuationFiredGate.TryEnter()) {\r
55                     _continuation();\r
56                 }\r
57             }\r
58         }\r
59 \r
60         public void SetContinuation(Action continuation) {\r
61             if (continuation != null) {\r
62                 _continuation = continuation;\r
63                 _setContinuationTrigger.Fire();\r
64             }\r
65         }\r
66 \r
67     }\r
68 }\r