1 //------------------------------------------------------------------------------
2 // <copyright file="SubscriptionQueue.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
7 namespace System.Web.Util {
9 using System.Collections.Generic;
12 // Similar to a Queue<T>, but allows unsubscribing from the underlying queue.
15 // Mutable struct for performance reasons; optimized for case where Enqueue is never called.
16 // Be careful with usage, e.g. no readonly declarations of this type.
18 // Type is not thread safe.
20 internal struct SubscriptionQueue<T> {
22 private LinkedList<T> _list;
25 get { return (_list == null || _list.Count == 0); }
28 public ISubscriptionToken Enqueue(T value) {
30 // lazily instantiate the list
31 _list = new LinkedList<T>();
34 LinkedListNode<T> node = _list.AddLast(value);
35 return new SubscriptionToken(node);
38 public void FireAndComplete(Action<T> action) {
41 // Use a while loop instead of a foreach since the list might be changing
42 while (TryDequeue(out value)) {
51 private bool TryDequeue(out T result) {
52 if (_list != null && _list.First != null) {
53 LinkedListNode<T> theNode = _list.First;
54 _list.RemoveFirst(); // also marks the SubscriptionToken as inactive
55 result = theNode.Value;
56 theNode.Value = default(T); // unroot the value in case it's large
60 result = default(T); // unroot the value in case it's large
65 private sealed class SubscriptionToken : ISubscriptionToken {
66 private readonly LinkedListNode<T> _node;
68 public SubscriptionToken(LinkedListNode<T> node) {
72 public bool IsActive {
73 get { return (_node.List != null); }
76 public void Unsubscribe() {
78 _node.List.Remove(_node);
79 _node.Value = default(T); // unroot the value in case it's large