File: System\Linq\Parallel\QueryOperators\Inlined\InlinedAggregationOperatorEnumerator.cs
Project: ndp\fx\src\Core\System.Core.csproj (System.Core)
// ==++==
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// InlinedAggregationOperatorEnumerator.cs
//
// <OWNER>Microsoft</OWNER>
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 
using System.Threading;
 
namespace System.Linq.Parallel
{
    //---------------------------------------------------------------------------------------
    // Inlined aggregate operators for finding the min/max values for primitives (int, long, float,
    // double, decimal).  Versions are also offered for the nullable primitives (int?, long?, float?,
    // double?, decimal?), which differ slightly in behavior: they return a null value for empty
    // streams, whereas the ordinary primitive versions throw.
    //
 
    //---------------------------------------------------------------------------------------
    // Inlined average operators for primitives (int, long, float, double, decimal), and the
    // nullable variants.  The difference between the nromal and nullable variety is that
    // nulls are skipped in tallying the count and sum for the average.
    //
 
    /// <summary>
    /// A class with some shared implementation between all aggregation enumerators. 
    /// </summary>
    /// <typeparam name="TIntermediate"></typeparam>
    internal abstract class InlinedAggregationOperatorEnumerator<TIntermediate> : QueryOperatorEnumerator<TIntermediate, int>
    {
        private int m_partitionIndex; // This partition's unique index.
        private bool m_done = false;
        protected CancellationToken m_cancellationToken;
 
        //---------------------------------------------------------------------------------------
        // Instantiates a new aggregation operator.
        //
 
        internal InlinedAggregationOperatorEnumerator(int partitionIndex, CancellationToken cancellationToken)
        {
            m_partitionIndex = partitionIndex;
            m_cancellationToken = cancellationToken;
        }
 
        //---------------------------------------------------------------------------------------
        // Tallies up the sum of the underlying data source, walking the entire thing the first
        // time MoveNext is called on this object. There is a boilerplate variant used by callers,
        // and then one that is used for extensibility by subclasses.
        //
 
        internal sealed override bool MoveNext(ref TIntermediate currentElement, ref int currentKey)
        {
            if (!m_done && MoveNextCore(ref currentElement))
            {
                // A reduction's "index" is the same as its partition number.
                currentKey = m_partitionIndex;
                m_done = true;
                return true;
            }
 
            return false;
        }
 
        protected abstract bool MoveNextCore(ref TIntermediate currentElement);
 
    }
}