1 namespace System.Web.Mvc.Async {
3 using System.Threading;
5 // This class is used to wait for triggers and a continuation. When the continuation has been provded
6 // and all triggers have been fired, the continuation is called. Similar to WaitHandle.WaitAll().
7 // New instances of this type are initially in the inactive state; activation is enabled by a call
10 // This class is thread-safe.
12 internal sealed class TriggerListener {
14 private readonly Trigger _activateTrigger;
15 private volatile Action _continuation;
16 private readonly SingleEntryGate _continuationFiredGate = new SingleEntryGate();
17 private int _outstandingTriggers;
18 private readonly Trigger _setContinuationTrigger;
20 public TriggerListener() {
21 _activateTrigger = CreateTrigger();
22 _setContinuationTrigger = CreateTrigger();
25 public void Activate() {
26 _activateTrigger.Fire();
29 public Trigger CreateTrigger() {
30 Interlocked.Increment(ref _outstandingTriggers);
32 SingleEntryGate triggerFiredGate = new SingleEntryGate();
33 return new Trigger(() => {
34 if (triggerFiredGate.TryEnter()) {
40 private void HandleTriggerFired() {
41 if (Interlocked.Decrement(ref _outstandingTriggers) == 0) {
42 if (_continuationFiredGate.TryEnter()) {
48 public void SetContinuation(Action continuation) {
49 if (continuation != null) {
50 _continuation = continuation;
51 _setContinuationTrigger.Fire();