public RowCursor(IChannelProvider provider, int poolRows, IRowCursor input, IRandom rand) : base(provider) { Ch.AssertValue(input); Ch.AssertValue(rand); Ch.Assert(_blockSize > 0); Ch.Assert(_bufferDepth > 0); Ch.Assert(poolRows > 0); _poolRows = poolRows; _input = input; _rand = rand; _pipeIndices = Utils.GetIdentityPermutation(_poolRows - 1 + _bufferDepth * _blockSize); int colLim = Schema.ColumnCount; int numActive = 0; _colToActivesIndex = new int[colLim]; for (int c = 0; c < colLim; ++c) { _colToActivesIndex[c] = _input.IsColumnActive(c) ? numActive++ : -1; } _pipes = new ShufflePipe[numActive + (int)ExtraIndex.Lim]; _getters = new Delegate[numActive]; for (int c = 0; c < colLim; ++c) { int ia = _colToActivesIndex[c]; if (ia < 0) { continue; } _pipes[ia] = ShufflePipe.Create(_pipeIndices.Length, input.Schema.GetColumnType(c), RowCursorUtils.GetGetterAsDelegate(input, c)); _getters[ia] = CreateGetterDelegate(c); } var idPipe = _pipes[numActive + (int)ExtraIndex.Id] = ShufflePipe.Create(_pipeIndices.Length, NumberType.UG, input.GetIdGetter()); _idGetter = CreateGetterDelegate <UInt128>(idPipe); // Initially, after the preamble to MoveNextCore, we want: // liveCount=0, deadCount=0, circularIndex=0. So we set these // funky values accordingly. _pipeIndex = _circularIndex = _pipeIndices.Length - 1; _deadCount = -1; _liveCount = 1; // Set up the producer worker. _toConsume = new BufferBlock <int>(); _toProduce = new BufferBlock <int>(); // First request the pool - 1 + block size rows, to get us going. PostAssert(_toProduce, _poolRows - 1 + _blockSize); // Queue up the remaining capacity. for (int i = 1; i < _bufferDepth; ++i) { PostAssert(_toProduce, _blockSize); } _producerTask = LoopProducerWorker(); }
private ValueGetter <TValue> CreateGetterDelegate <TValue>(ShufflePipe pipe) { Ch.AssertValue(pipe); Ch.Assert(pipe is ShufflePipe <TValue>); var pipe2 = (ShufflePipe <TValue>)pipe; ValueGetter <TValue> getter = (ref TValue value) => { Ch.Assert(_pipeIndex == _pipeIndices[_circularIndex]); pipe2.Fetch(_pipeIndex, ref value); }; return(getter); }