RangeEnumerable.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / System / Linq / Parallel / Enumerables / RangeEnumerable.cs / 1305376 / RangeEnumerable.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// 
// RangeEnumerable.cs 
//
// [....] 
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

using System.Collections.Generic; 

namespace System.Linq.Parallel 
{ 
    /// 
    /// A simple enumerable type that implements the range algorithm. It also supports 
    /// partitioning of the indices by implementing an interface that PLINQ recognizes.
    /// 
    internal class RangeEnumerable : ParallelQuery, IParallelPartitionable
    { 

        private int m_from; // Lowest index to include. 
        private int m_count; // Number of indices to include. 

        //------------------------------------------------------------------------------------ 
        // Constructs a new range enumerable object for the specified range.
        //

        internal RangeEnumerable(int from, int count) 
            :base(QuerySettings.Empty)
        { 
            // Transform the from and to indices into low and highs. 
            m_from = from;
            m_count = count; 
        }

        //-----------------------------------------------------------------------------------
        // Retrieves 'count' partitions, each of which uses a non-overlapping set of indices. 
        //
 
        public QueryOperatorEnumerator[] GetPartitions(int partitionCount) 
        {
            // Calculate a stride size, avoiding overflow if m_count is large 
            int stride = m_count / partitionCount;
            int biggerPartitionCount = m_count % partitionCount;

            // Create individual partitions, carefully avoiding overflow 
            int doneCount = 0;
            QueryOperatorEnumerator[] partitions = new QueryOperatorEnumerator[partitionCount]; 
            for (int i = 0; i < partitionCount; i++) 
            {
                int partitionSize = (i < biggerPartitionCount) ? stride + 1 : stride; 
                partitions[i] = new RangeEnumerator(
                    m_from + doneCount,
                    partitionSize,
                    doneCount); 
                doneCount += partitionSize;
            } 
 
            return partitions;
        } 

        //-----------------------------------------------------------------------------------
        // Basic IEnumerator method implementations.
        // 

        public override IEnumerator GetEnumerator() 
        { 
            return new RangeEnumerator(m_from, m_count, 0).AsClassicEnumerator();
        } 

        //-----------------------------------------------------------------------------------
        // The actual enumerator that walks over the specified range.
        // 

        class RangeEnumerator : QueryOperatorEnumerator 
        { 

            private readonly int m_from; // The initial value. 
            private readonly int m_count; // How many values to yield.
            private readonly int m_initialIndex; // The ordinal index of the first value in the range.
            private Shared m_currentCount; // The 0-based index of the current value. [allocate in moveNext to avoid false-sharing]
 
            //------------------------------------------------------------------------------------
            // Creates a new enumerator. 
            // 

            internal RangeEnumerator(int from, int count, int initialIndex) 
            {
                m_from = from;
                m_count = count;
                m_initialIndex = initialIndex; 
            }
 
            //----------------------------------------------------------------------------------- 
            // Basic enumeration method. This implements the logic to walk the desired
            // range, using the step specified at construction time. 
            //

            internal override bool MoveNext(ref int currentElement, ref int currentKey)
            { 
                if( m_currentCount == null)
                    m_currentCount = new Shared(-1); 
 
                // Calculate the next index and ensure it falls within our range.
                int nextCount = m_currentCount.Value + 1; 
                if (nextCount < m_count)
                {
                    m_currentCount.Value = nextCount;
                    currentElement = nextCount + m_from; 
                    currentKey = nextCount + m_initialIndex;
                    return true; 
                } 

                return false; 
            }

            internal override void Reset()
            { 
                // We set the current value such that the next addition of step
                // results in the 1st real value in the range. 
                m_currentCount = null; 
            }
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK