| File: Data\SlotCursor.cs | Web Access |
| Project: src\src\Microsoft.ML.Data\Microsoft.ML.Data.csproj (Microsoft.ML.Data) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using Microsoft.ML.Runtime; namespace Microsoft.ML.Data { /// <summary> /// A cursor that allows slot-by-slot access of data. This is to <see cref="ITransposeDataView"/> /// what <see cref="DataViewRowCursor"/> is to <see cref="IDataView"/>. /// </summary> [BestFriend] internal abstract class SlotCursor : IDisposable { [BestFriend] private protected readonly IChannel Ch; private bool _started; protected bool Disposed { get; private set; } /// <summary> /// Whether the cursor is in a state where it can serve up data, that is, <see cref="MoveNext"/> /// has been called and returned <see langword="true"/>. /// </summary> [BestFriend] private protected bool IsGood => _started && !Disposed; [BestFriend] private protected SlotCursor(IChannelProvider provider) { Contracts.AssertValue(provider); Ch = provider.Start("Slot Cursor"); } /// <summary> /// The slot index. Incremented by one when <see cref="MoveNext"/> is called and returns <see langword="true"/>. /// When initially created, or after <see cref="MoveNext"/> returns <see langword="false"/>, this will be <c>-1</c>. /// </summary> public abstract int SlotIndex { get; } /// <summary> /// Advance to the next slot. When the cursor is first created, this method should be called to /// move to the first slot. Returns <see langword="false"/> if there are no more slots. /// </summary> public abstract bool MoveNext(); /// <summary> /// The slot type for this cursor. Note that this should equal the /// <see cref="ITransposeDataView.GetSlotType"/> for the column from which this slot cursor /// was created. /// </summary> public abstract VectorDataViewType GetSlotType(); /// <summary> /// A getter delegate for the slot values. The type <typeparamref name="TValue"/> must correspond /// to the item type from <see cref="ITransposeDataView.GetSlotType"/>. /// </summary> public abstract ValueGetter<VBuffer<TValue>> GetGetter<TValue>(); public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (Disposed) return; if (disposing) Ch.Dispose(); Disposed = true; } /// <summary> /// For wrapping another slot cursor from which we get <see cref="SlotIndex"/> and <see cref="MoveNext"/>, /// but not the data or type accesors. Somewhat analogous to the <see cref="SynchronizedCursorBase"/> /// for <see cref="DataViewRowCursor"/>s. /// </summary> [BestFriend] internal abstract class SynchronizedSlotCursor : SlotCursor { private readonly SlotCursor _root; public SynchronizedSlotCursor(IChannelProvider provider, SlotCursor cursor) : base(provider) { Contracts.AssertValue(cursor); // If the input is itself a sync-base, we can walk up the chain to get its root, // thereby making things more efficient. _root = cursor is SynchronizedSlotCursor sync ? sync._root : cursor; } public override bool MoveNext() => _root.MoveNext(); public override int SlotIndex => _root.SlotIndex; } /// <summary> /// A useful base class for common <see cref="SlotCursor"/> implementations, somewhat /// analogous to the <see cref="RootCursorBase"/> for <see cref="DataViewRowCursor"/>s. /// </summary> [BestFriend] internal abstract class RootSlotCursor : SlotCursor { private int _slotIndex; public RootSlotCursor(IChannelProvider provider) : base(provider) { _slotIndex = -1; } public override int SlotIndex => _slotIndex; protected sealed override void Dispose(bool disposing) { if (Disposed) return; if (disposing) _slotIndex = -1; base.Dispose(disposing); } public override bool MoveNext() { if (Disposed) return true; if (MoveNextCore()) { _slotIndex++; Ch.Assert(_slotIndex >= 0); _started = true; return true; } Dispose(); Ch.Assert(_slotIndex < 0); return false; } /// <summary> /// Core implementation of <see cref="MoveNext"/>. This is called only if this method /// has not yet previously returned <see langword="false"/>. /// </summary> protected abstract bool MoveNextCore(); } } }