Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Core / System / Linq / Parallel / Utils / ListChunk.cs
1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
7 //
8 // ListChunk.cs
9 //
10 // <OWNER>[....]</OWNER>
11 //
12 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
13
14 using System.Collections.Generic;
15 using System.Diagnostics.Contracts;
16
17 namespace System.Linq.Parallel
18 {
19     /// <summary>
20     /// A linked list of array chunks. Allows direct access to its arrays.
21     /// </summary>
22     /// <typeparam name="TInputOutput">The elements held within.</typeparam>
23     internal class ListChunk<TInputOutput> : IEnumerable<TInputOutput>
24     {
25         internal TInputOutput[] m_chunk;
26         private int m_chunkCount;
27         private ListChunk<TInputOutput> m_nextChunk;
28         private ListChunk<TInputOutput> m_tailChunk;
29
30         /// <summary>
31         /// Allocates a new root chunk of a particular size.
32         /// </summary>
33         internal ListChunk(int size)
34         {
35             Contract.Assert(size > 0);
36             m_chunk = new TInputOutput[size];
37             m_chunkCount = 0;
38             m_tailChunk = this;
39         }
40
41         /// <summary>
42         /// Adds an element to this chunk.  Only ever called on the root.
43         /// </summary>
44         /// <param name="e">The new element.</param>
45         internal void Add(TInputOutput e)
46         {
47             ListChunk<TInputOutput> tail = m_tailChunk;
48             if (tail.m_chunkCount == tail.m_chunk.Length)
49             {
50                 m_tailChunk = new ListChunk<TInputOutput>(tail.m_chunkCount * 2);
51                 tail = (tail.m_nextChunk = m_tailChunk);
52             }
53
54             tail.m_chunk[tail.m_chunkCount++] = e;
55         }
56
57         /// <summary>
58         /// The next chunk in the linked chain.
59         /// </summary>
60         internal ListChunk<TInputOutput> Next
61         {
62             get { return m_nextChunk; }
63         }
64
65         /// <summary>
66         /// The number of elements contained within this particular chunk.
67         /// </summary>
68         internal int Count
69         {
70             get { return m_chunkCount; }
71         }
72
73         /// <summary>
74         /// Fetches an enumerator to walk the elements in all chunks rooted from this one.
75         /// </summary>
76         public IEnumerator<TInputOutput> GetEnumerator()
77         {
78             ListChunk<TInputOutput> curr = this;
79             while (curr != null)
80             {
81                 for (int i = 0; i < curr.m_chunkCount; i++)
82                 {
83                     yield return curr.m_chunk[i];
84                 }
85                 Contract.Assert(curr.m_chunkCount == curr.m_chunk.Length || curr.m_nextChunk == null);
86                 curr = curr.m_nextChunk;
87             }
88         }
89
90         System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
91         {
92             return ((IEnumerable<TInputOutput>)this).GetEnumerator();
93         }
94     }
95 }