Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
PSDataCollection.cs2122 linesDownload Raw Back to hostifaces
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.Generic;6using System.Collections.ObjectModel;7using System.Diagnostics.CodeAnalysis; // for fxcop8using System.Reflection;9using System.Runtime.Serialization;10using System.Threading;11 12using Dbg = System.Management.Automation.Diagnostics;13 14namespace System.Management.Automation15{16    #region DataAddedEventArgs17 18    /// <summary>19    /// Event arguments passed to PSDataCollection DataAdded handlers.20    /// </summary>21    public sealed class DataAddedEventArgs : EventArgs22    {23        #region Private Data24 25        #endregion26 27        #region Constructor28 29        /// <summary>30        /// Constructor.31        /// </summary>32        /// <param name="psInstanceId">33        /// PowerShell InstanceId which added this data.34        /// Guid.Empty, if the data is not added by a PowerShell35        /// instance.36        /// </param>37        /// <param name="index">38        /// Index at which the data is added.39        /// </param>40        internal DataAddedEventArgs(Guid psInstanceId, int index)41        {42            PowerShellInstanceId = psInstanceId;43            Index = index;44        }45 46        #endregion47 48        #region Properties49 50        /// <summary>51        /// Index at which the data is added.52        /// </summary>53        public int Index { get; }54 55        /// <summary>56        /// PowerShell InstanceId which added this data.57        /// Guid.Empty, if the data is not added by a PowerShell58        /// instance.59        /// </summary>60        public Guid PowerShellInstanceId { get; }61 62        #endregion63    }64 65    #endregion66 67    /// <summary>68    /// Event arguments passed to PSDataCollection DataAdding handlers.69    /// </summary>70    public sealed class DataAddingEventArgs : EventArgs71    {72        #region Private Data73 74        #endregion75 76        #region Constructor77 78        /// <summary>79        /// Constructor.80        /// </summary>81        /// <param name="psInstanceId">82        /// PowerShell InstanceId which added this data.83        /// Guid.Empty, if the data is not added by a PowerShell84        /// instance.85        /// </param>86        /// <param name="itemAdded">87        /// The actual item about to be added.88        /// </param>89        internal DataAddingEventArgs(Guid psInstanceId, object itemAdded)90        {91            PowerShellInstanceId = psInstanceId;92            ItemAdded = itemAdded;93        }94 95        #endregion96 97        #region Properties98 99        /// <summary>100        /// The item about to be added.101        /// </summary>102        public object ItemAdded { get; }103 104        /// <summary>105        /// PowerShell InstanceId which added this data.106        /// Guid.Empty, if the data is not added by a PowerShell107        /// instance.108        /// </summary>109        public Guid PowerShellInstanceId { get; }110 111        #endregion112    }113 114    #region PSDataCollection115 116    /// <summary>build117    /// Thread Safe buffer used with PowerShell Hosting interfaces.118    /// </summary>119    public class PSDataCollection<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable, IDisposable, ISerializable120    {121        #region Private Data122 123        private readonly IList<T> _data;124        private ManualResetEvent _readWaitHandle;125        private bool _isOpen = true;126        private bool _releaseOnEnumeration;127        private bool _isEnumerated;128        // a counter to keep track of active PowerShell instances129        // using this buffer.130        private int _refCount;131 132        private bool _isDisposed = false;133 134        /// <summary>135        /// Whether the enumerator needs to be blocking136        /// by default.137        /// </summary>138        private bool _blockingEnumerator = false;139 140        /// <summary>141        /// Whether the ref count was incremented when142        /// BlockingEnumerator was updated.143        /// </summary>144        private bool _refCountIncrementedForBlockingEnumerator = false;145 146        private int _countNewData = 0;147        private int _dataAddedFrequency = 1;148        private Guid _sourceGuid = Guid.Empty;149 150        #endregion151 152        #region Public Constructors153 154        /// <summary>155        /// Default Constructor.156        /// </summary>157        public PSDataCollection() : this(new List<T>())158        {159        }160 161        /// <summary>162        /// Creates a PSDataCollection that includes all the items in the IEnumerable and invokes Complete().163        /// </summary>164        /// <param name="items">165        /// Items used to initialize the collection166        /// </param>167        /// <remarks>168        /// This constructor is useful when the user wants to use an IEnumerable as an input to one of the PowerShell.BeginInvoke overloads.169        /// The invocation doesn't complete until Complete() is called on the PSDataCollection; this constructor does the Complete() on170        /// behalf of the user.171        /// </remarks>172        public PSDataCollection(IEnumerable<T> items) : this(new List<T>(items))173        {174            this.Complete();175        }176 177        /// <summary>178        /// Initializes a new instance with the specified capacity179        /// <paramref name="capacity"/>180        /// </summary>181        /// <param name="capacity">182        /// The number of elements that the new buffer can initially183        /// store.184        /// </param>185        /// <remarks>186        /// Capacity is the number of elements that the PSDataCollection can187        /// store before resizing is required.188        /// </remarks>189        public PSDataCollection(int capacity) : this(new List<T>(capacity))190        {191        }192 193        #endregion194 195        #region type converters196 197        /// <summary>198        /// Wrap the argument in a PSDataCollection.199        /// </summary>200        /// <param name="valueToConvert">The value to convert.</param>201        /// <returns>New collection of value, marked as Complete.</returns>202        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates",203            Justification = "There are already alternates to the implicit casts, ToXXX and FromXXX methods are unnecessary and redundant")]204        public static implicit operator PSDataCollection<T>(bool valueToConvert)205        {206            return CreateAndInitializeFromExplicitValue(valueToConvert);207        }208 209        /// <summary>210        /// Wrap the argument in a PSDataCollection.211        /// </summary>212        /// <param name="valueToConvert">The value to convert.</param>213        /// <returns>New collection of value, marked as Complete.</returns>214        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates",215            Justification = "There are already alternates to the implicit casts, ToXXX and FromXXX methods are unnecessary and redundant")]216        public static implicit operator PSDataCollection<T>(string valueToConvert)217        {218            return CreateAndInitializeFromExplicitValue(valueToConvert);219        }220 221        /// <summary>222        /// Wrap the argument in a PSDataCollection.223        /// </summary>224        /// <param name="valueToConvert">The value to convert.</param>225        /// <returns>New collection of value, marked as Complete.</returns>226        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates",227            Justification = "There are already alternates to the implicit casts, ToXXX and FromXXX methods are unnecessary and redundant")]228        public static implicit operator PSDataCollection<T>(int valueToConvert)229        {230            return CreateAndInitializeFromExplicitValue(valueToConvert);231        }232 233        /// <summary>234        /// Wrap the argument in a PSDataCollection.235        /// </summary>236        /// <param name="valueToConvert">The value to convert.</param>237        /// <returns>New collection of value, marked as Complete.</returns>238        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates",239            Justification = "There are already alternates to the implicit casts, ToXXX and FromXXX methods are unnecessary and redundant")]240        public static implicit operator PSDataCollection<T>(byte valueToConvert)241        {242            return CreateAndInitializeFromExplicitValue(valueToConvert);243        }244 245        private static PSDataCollection<T> CreateAndInitializeFromExplicitValue(object valueToConvert)246        {247            PSDataCollection<T> psdc = new PSDataCollection<T>();248            psdc.Add(LanguagePrimitives.ConvertTo<T>(valueToConvert));249            psdc.Complete();250            return psdc;251        }252 253        /// <summary>254        /// Wrap the argument in a PSDataCollection.255        /// </summary>256        /// <param name="valueToConvert">The value to convert.</param>257        /// <returns>New collection of value, marked as Complete.</returns>258        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates",259            Justification = "There are already alternates to the implicit casts, ToXXX and FromXXX methods are unnecessary and redundant")]260        public static implicit operator PSDataCollection<T>(Hashtable valueToConvert)261        {262            PSDataCollection<T> psdc = new PSDataCollection<T>();263            psdc.Add(LanguagePrimitives.ConvertTo<T>(valueToConvert));264            psdc.Complete();265            return psdc;266        }267 268        /// <summary>269        /// Wrap the argument in a PSDataCollection.270        /// </summary>271        /// <param name="valueToConvert">The value to convert.</param>272        /// <returns>New collection of value, marked as Complete.</returns>273        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates",274            Justification = "There are already alternates to the implicit casts, ToXXX and FromXXX methods are unnecessary and redundant")]275        public static implicit operator PSDataCollection<T>(T valueToConvert)276        {277            PSDataCollection<T> psdc = new PSDataCollection<T>();278            psdc.Add(LanguagePrimitives.ConvertTo<T>(valueToConvert));279            psdc.Complete();280            return psdc;281        }282 283        /// <summary>284        /// Wrap the argument in a PSDataCollection.285        /// </summary>286        /// <param name="arrayToConvert">The value to convert.</param>287        /// <returns>New collection of value, marked as Complete.</returns>288        [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates",289            Justification = "There are already alternates to the implicit casts, ToXXX and FromXXX methods are unnecessary and redundant")]290        public static implicit operator PSDataCollection<T>(object[] arrayToConvert)291        {292            PSDataCollection<T> psdc = new PSDataCollection<T>();293            if (arrayToConvert != null)294            {295                foreach (var ae in arrayToConvert)296                {297                    psdc.Add(LanguagePrimitives.ConvertTo<T>(ae));298                }299            }300 301            psdc.Complete();302            return psdc;303        }304 305        #endregion306 307        #region Internal Constructor308 309        /// <summary>310        /// Construct the DataBuffer using the supplied <paramref name="listToUse"/>311        /// as the data buffer.312        /// </summary>313        /// <param name="listToUse">314        /// buffer where the elements are stored315        /// </param>316        /// <remarks>317        /// Using this constructor will make the data buffer a wrapper on318        /// top of the <paramref name="listToUse"/>, which provides synchronized319        /// access.320        /// </remarks>321        internal PSDataCollection(IList<T> listToUse)322        {323            _data = listToUse;324        }325 326        /// <summary>327        /// Creates a PSDataCollection from an ISerializable context.328        /// </summary>329        /// <param name="info">Serialization information for this instance.</param>330        /// <param name="context">The streaming context for this instance.</param>331        protected PSDataCollection(SerializationInfo info, StreamingContext context)332        {333            if (info == null)334            {335                throw PSTraceSource.NewArgumentNullException(nameof(info));336            }337 338            if (info.GetValue("Data", typeof(IList<T>)) is not IList<T> listToUse)339            {340                throw PSTraceSource.NewArgumentNullException(nameof(info));341            }342 343            _data = listToUse;344 345            _blockingEnumerator = info.GetBoolean("BlockingEnumerator");346            _dataAddedFrequency = info.GetInt32("DataAddedCount");347            EnumeratorNeverBlocks = info.GetBoolean("EnumeratorNeverBlocks");348            _isOpen = info.GetBoolean("IsOpen");349        }350 351        #endregion352 353        #region PSDataCollection Specific Public Methods / Properties354 355        /// <summary>356        /// Event fired when objects are being added to the underlying buffer.357        /// </summary>358        public event EventHandler<DataAddingEventArgs> DataAdding;359 360        /// <summary>361        /// Event fired when objects are done being added to the underlying buffer.362        /// </summary>363        public event EventHandler<DataAddedEventArgs> DataAdded;364 365        /// <summary>366        /// Event fired when the buffer is completed.367        /// </summary>368        public event EventHandler Completed;369 370        /// <summary>371        /// A boolean which determines if the buffer is open.372        /// </summary>373        public bool IsOpen374        {375            get376            {377                lock (SyncObject)378                {379                    return _isOpen;380                }381            }382        }383 384        /// <summary>385        /// An int that tells the frequency of Data Added events fired.386        /// Raises the DataAdded event only when data has been added a multiple of this many times,387        /// or when collection can receive no more data, if further data is added past the last event388        /// prior to completion.389        /// </summary>390        public int DataAddedCount391        {392            get393            {394                return _dataAddedFrequency;395            }396 397            set398            {399                bool raiseDataAdded = false;400                lock (SyncObject)401                {402                    _dataAddedFrequency = value;403                    if (_countNewData >= _dataAddedFrequency)404                    {405                        raiseDataAdded = true;406                        _countNewData = 0;407                    }408                }409 410                if (raiseDataAdded)411                {412                    // We should raise the event outside of the lock413                    // as the call is made into 3rd party code414                    RaiseDataAddedEvent(_lastPsInstanceId, _lastIndex);415                }416            }417        }418 419        /// <summary>420        /// Serializes all input by default.421        /// This is supported only for PSDataCollections of PSObject.422        /// </summary>423        public bool SerializeInput424        {425            get426            {427                return _serializeInput;428            }429 430            set431            {432                if (typeof(T) != typeof(PSObject))433                {434                    // If you drop this constraint, GetSerializedInput must be updated.435                    throw new NotSupportedException(PSDataBufferStrings.SerializationNotSupported);436                }437 438                _serializeInput = value;439            }440        }441 442        private bool _serializeInput = false;443 444        /// <summary>445        /// Determines whether this PSDataCollection was created implicitly in support of446        /// data collection (for example, a workflow that wants to capture output but hasn't447        /// provided an instance of the PSDataCollection to capture it with.)448        /// </summary>449        public bool IsAutoGenerated450        {451            get; set;452        }453 454        /// <summary>455        /// Internal tag for indicating a source object identifier for this collection.456        /// </summary>457        internal Guid SourceId458        {459            get460            {461                lock (SyncObject)462                {463                    return _sourceGuid;464                }465            }466 467            set468            {469                lock (SyncObject)470                {471                    _sourceGuid = value;472                }473            }474        }475 476        /// <summary>477        /// If this flag is set to true, the items in the collection will be set to null when it is478        /// traversed using a PSDataCollectionEnumerator.479        /// </summary>480        internal bool ReleaseOnEnumeration481        {482            get483            {484                lock (SyncObject)485                {486                    return _releaseOnEnumeration;487                }488            }489 490            set491            {492                lock (SyncObject)493                {494                    _releaseOnEnumeration = value;495                }496            }497        }498 499        /// <summary>500        /// This flag is true when the collection has been enumerated at least once by a PSDataCollectionEnumerator.501        /// </summary>502        internal bool IsEnumerated503        {504            get505            {506                lock (SyncObject)507                {508                    return _isEnumerated;509                }510            }511 512            set513            {514                lock (SyncObject)515                {516                    _isEnumerated = value;517                }518            }519        }520 521        /// <summary>522        /// Completes insertions to the buffer.523        /// Subsequent Inserts to the buffer will result in an InvalidOperationException.524        /// </summary>525        public void Complete()526        {527            bool raiseEvents = false;528            bool raiseDataAdded = false;529            try530            {531                // Close the buffer532                lock (SyncObject)533                {534                    if (_isOpen)535                    {536                        _isOpen = false;537                        raiseEvents = true;538                        // release any threads to notify an event. Enumerator539                        // blocks on this syncObject.540                        Monitor.PulseAll(SyncObject);541 542                        if (_countNewData > 0)543                        {544                            raiseDataAdded = true;545                            _countNewData = 0;546                        }547                    }548                }549            }550            finally551            {552                // raise the events outside of the lock.553                if (raiseEvents)554                {555                    // unblock any readers waiting on the handle556                    _readWaitHandle?.Set();557 558                    // A temporary variable is used as the Completed may559                    // reach null (because of -='s) after the null check560                    Completed?.Invoke(this, EventArgs.Empty);561                }562 563                if (raiseDataAdded)564                {565                    RaiseDataAddedEvent(_lastPsInstanceId, _lastIndex);566                }567            }568        }569 570        /// <summary>571        /// Indicates whether the data collection should572        /// have a blocking enumerator by default. Currently573        /// only when a PowerShell object is associated with574        /// the data collection, a reference count is added575        /// which causes the enumerator to be blocking. This576        /// prevents the use of PSDataCollection without a577        /// PowerShell object. This property fixes the same.578        /// </summary>579        public bool BlockingEnumerator580        {581            get582            {583                lock (SyncObject)584                {585                    return _blockingEnumerator;586                }587            }588 589            set590            {591                lock (SyncObject)592                {593                    _blockingEnumerator = value;594 595                    if (_blockingEnumerator)596                    {597                        if (!_refCountIncrementedForBlockingEnumerator)598                        {599                            _refCountIncrementedForBlockingEnumerator = true;600                            AddRef();601                        }602                    }603                    else604                    {605                        // TODO: false doesn't always leading to non-blocking606                        // behavior in an intuitive way. Need to follow up607                        // and fix this608                        if (_refCountIncrementedForBlockingEnumerator)609                        {610                            _refCountIncrementedForBlockingEnumerator = false;611                            DecrementRef();612                        }613                    }614                }615            }616        }617 618        /// <summary>619        /// If this is set to true, then the enumerator returned from620        /// GetEnumerator() will never block.621        /// </summary>622        public bool EnumeratorNeverBlocks { get; set; }623 624        #endregion625 626        #region IList Generic Overrides627 628        /// <summary>629        /// Gets or sets the element at the specified index.630        /// </summary>631        /// <param name="index">632        /// The zero-based index of the element to get or set.633        /// </param>634        /// <exception cref="InvalidOperationException">635        /// Objects cannot be added to a closed buffer.636        /// Make sure the buffer is open for Add and Insert637        /// operations to succeed.638        /// </exception>639        /// <exception cref="ArgumentOutOfRangeException">640        /// index is less than 0.641        /// (or)642        /// index is equal to or greater than Count.643        /// </exception>644        public T this[int index]645        {646            get647            {648                lock (SyncObject)649                {650                    return _data[index];651                }652            }653 654            set655            {656                lock (SyncObject)657                {658                    if ((index < 0) || (index >= _data.Count))659                    {660                        throw PSTraceSource.NewArgumentOutOfRangeException(nameof(index), index,661                            PSDataBufferStrings.IndexOutOfRange, 0, _data.Count - 1);662                    }663 664                    if (_serializeInput)665                    {666                        value = (T)(object)GetSerializedObject(value);667                    }668 669                    _data[index] = value;670                }671            }672        }673 674        /// <summary>675        /// Determines the index of a specific item in the buffer.676        /// </summary>677        /// <param name="item">678        /// The object to locate in the buffer.679        /// </param>680        /// <returns>681        /// The index of item if found in the buffer; otherwise, -1.682        /// </returns>683        public int IndexOf(T item)684        {685            lock (SyncObject)686            {687                return InternalIndexOf(item);688            }689        }690 691        /// <summary>692        /// Inserts an item to the buffer at the specified index.693        /// </summary>694        /// <param name="index">695        /// The zero-based index at which item should be inserted.696        /// </param>697        /// <param name="item">698        /// The object to insert into the buffer.699        /// </param>700        /// <exception cref="InvalidOperationException">701        /// Objects cannot be added to a closed buffer.702        /// Make sure the buffer is open for Add and Insert703        /// operations to succeed.704        /// </exception>705        /// <exception cref="ArgumentOutOfRangeException">706        /// The index specified is less than zero or greater707        /// than Count.708        /// </exception>709        public void Insert(int index, T item)710        {711            lock (SyncObject)712            {713                InternalInsertItem(Guid.Empty, index, item);714            }715 716            RaiseEvents(Guid.Empty, index);717        }718 719        /// <summary>720        /// Removes the item at the specified index.721        /// </summary>722        /// <param name="index">723        /// The zero-based index of the item to remove.724        /// </param>725        /// <exception cref="ArgumentOutOfRangeException">726        /// index is not a valid index in the buffer.727        /// </exception>728        public void RemoveAt(int index)729        {730            lock (SyncObject)731            {732                if ((index < 0) || (index >= _data.Count))733                {734                    throw PSTraceSource.NewArgumentOutOfRangeException(nameof(index), index,735                        PSDataBufferStrings.IndexOutOfRange, 0, _data.Count - 1);736                }737 738                RemoveItem(index);739            }740        }741 742        #endregion743 744        #region ICollection Generic Overrides745 746        /// <summary>747        /// Gets the number of elements contained in the buffer.748        /// </summary>749        public int Count750        {751            get752            {753                lock (SyncObject)754                {755                    if (_data == null)756                        return 0;757                    else758                        return _data.Count;759                }760            }761        }762 763        /// <summary>764        /// Gets a value indicating whether the buffer is read-only.765        /// </summary>766        public bool IsReadOnly767        {768            get769            {770                return false;771            }772        }773 774        /// <summary>775        /// Adds an item to the thread-safe buffer.776        /// </summary>777        /// <param name="item">778        /// item to add779        /// </param>780        /// <exception cref="InvalidOperationException">781        /// Objects cannot be added to a closed buffer.782        /// Make sure the buffer is open for Add and Insert783        /// operations to succeed.784        /// </exception>785        public void Add(T item)786        {787            InternalAdd(Guid.Empty, item);788        }789 790        /// <summary>791        /// Removes all items from the buffer.792        /// </summary>793        public void Clear()794        {795            lock (SyncObject)796            {797                _data?.Clear();798            }799        }800 801        /// <summary>802        /// Determines whether the buffer contains an element with a specific value.803        /// </summary>804        /// <param name="item">805        /// The object to locate in the buffer.806        /// </param>807        /// <returns>808        /// true if the element value is found in the buffer; otherwise false.809        /// </returns>810        public bool Contains(T item)811        {812            lock (SyncObject)813            {814                if (_serializeInput)815                {816                    item = (T)(object)GetSerializedObject(item);817                }818 819                return _data.Contains(item);820            }821        }822 823        /// <summary>824        /// Copies the elements of the buffer to a specified array, starting at a particular index.825        /// </summary>826        /// <param name="array">827        /// The destination Array for the elements of type T copied from the buffer.828        /// </param>829        /// <param name="arrayIndex">830        /// The zero-based index in the array at which copying begins.831        /// </param>832        /// <exception cref="ArgumentException">833        /// array is multidimensional.834        /// (or)835        /// arrayIndex is equal to or greater than the length of array.836        /// (or)837        /// The number of elements in the source buffer is greater than the838        /// available space from arrayIndex to the end of the destination array.839        /// (or)840        /// Type T cannot be cast automatically to the type of the destination array.841        /// </exception>842        /// <exception cref="ArgumentNullException">843        /// array is a null reference844        /// </exception>845        /// <exception cref="ArgumentOutOfRangeException">846        /// arrayIndex is less than 0.847        /// </exception>848        public void CopyTo(T[] array, int arrayIndex)849        {850            lock (SyncObject)851            {852                _data.CopyTo(array, arrayIndex);853            }854        }855 856        /// <summary>857        /// Removes the first occurrence of a specified item from the buffer.858        /// </summary>859        /// <param name="item">860        /// The object to remove from the buffer.861        /// </param>862        /// <returns>863        /// true if item was successfully removed from the buffer; otherwise, false.864        /// </returns>865        public bool Remove(T item)866        {867            lock (SyncObject)868            {869                int index = InternalIndexOf(item);870                if (index < 0)871                {872                    return false;873                }874 875                RemoveItem(index);876                return true;877            }878        }879 880        #endregion881 882        #region IEnumerable Generic Overrides883 884        /// <summary>885        /// Returns an enumerator that iterates through the886        /// elements of the buffer.887        /// </summary>888        /// <returns>889        /// An IEnumerator for objects of the type stored in the buffer.890        /// </returns>891        public IEnumerator<T> GetEnumerator()892        {893            return new PSDataCollectionEnumerator<T>(this, EnumeratorNeverBlocks);894        }895 896        #endregion897 898        #region IList Overrides899 900        /// <summary>901        /// Adds an element to the buffer.902        /// </summary>903        /// <param name="value">904        /// The object to add to the buffer.905        /// </param>906        /// <returns>907        /// The position into which the new element was inserted.908        /// </returns>909        /// <exception cref="InvalidOperationException">910        /// Objects cannot be added to a closed buffer.911        /// Make sure the buffer is open for Add and Insert912        /// operations to succeed.913        /// </exception>914        /// <exception cref="ArgumentException">915        /// value reference is null.916        /// (or)917        /// value is not of the correct generic type T for the buffer.918        /// </exception>919        int IList.Add(object value)920        {921            PSDataCollection<T>.VerifyValueType(value);922            int index = _data.Count;923            InternalAdd(Guid.Empty, (T)value);924            RaiseEvents(Guid.Empty, index);925 926            return index;927        }928 929        /// <summary>930        /// Determines whether the collection contains an931        /// element with a specific value.932        /// </summary>933        /// <param name="value">934        /// The object to locate in the collection935        /// </param>936        /// <returns>937        /// true if the element value is found in the collection;938        /// otherwise false.939        /// </returns>940        /// <exception cref="ArgumentException">941        /// value reference is null.942        /// (or)943        /// value is not of the correct generic type T for the buffer.944        /// </exception>945        bool IList.Contains(object value)946        {947            PSDataCollection<T>.VerifyValueType(value);948            return Contains((T)value);949        }950 951        /// <summary>952        /// Determines the zero-based index of an element in the buffer.953        /// </summary>954        /// <param name="value">955        /// The element in the buffer whose index is being determined.956        /// </param>957        /// <returns>958        /// The index of the value if found in the buffer; otherwise, -1.959        /// </returns>960        /// <exception cref="ArgumentException">961        /// value reference is null.962        /// (or)963        /// value is not of the correct generic type T for the buffer.964        /// </exception>965        int IList.IndexOf(object value)966        {967            PSDataCollection<T>.VerifyValueType(value);968            return IndexOf((T)value);969        }970 971        /// <summary>972        /// Inserts an object into the buffer at a specified index.973        /// </summary>974        /// <param name="index">975        /// The zero-based index at which value is to be inserted.976        /// </param>977        /// <param name="value">978        /// The object to insert into the buffer.979        /// </param>980        /// <exception cref="ArgumentOutOfRangeException">981        /// index is not a valid index in the buffer.982        /// </exception>983        /// <exception cref="ArgumentException">984        /// value reference is null.985        /// (or)986        /// value is not of the correct generic type T for the buffer.987        /// </exception>988        void IList.Insert(int index, object value)989        {990            PSDataCollection<T>.VerifyValueType(value);991            Insert(index, (T)value);992        }993 994        /// <summary>995        /// Removes the first occurrence of a specified object996        /// as an element from the buffer.997        /// </summary>998        /// <param name="value">999        /// The object to be removed from the buffer.1000        /// </param>1001        /// <exception cref="ArgumentException">1002        /// value reference is null.1003        /// (or)1004        /// value is not of the correct generic type T for the buffer.1005        /// </exception>1006        void IList.Remove(object value)1007        {1008            PSDataCollection<T>.VerifyValueType(value);1009            Remove((T)value);1010        }1011 1012        /// <summary>1013        /// Gets a value that indicates whether the buffer is fixed in size.1014        /// </summary>1015        bool IList.IsFixedSize1016        {1017            get1018            {1019                return false;1020            }1021        }1022 1023        /// <summary>1024        /// Gets a value that indicates whether the buffer is read-only.1025        /// </summary>1026        bool IList.IsReadOnly1027        {1028            get1029            {1030                return false;1031            }1032        }1033 1034        /// <summary>1035        /// Gets or sets the element at the specified index.1036        /// </summary>1037        /// <param name="index">1038        /// The zero-based index of the element to get or set.1039        /// </param>1040        /// <exception cref="IndexOutOfRangeException">1041        /// index is less than 0.1042        /// (or)1043        /// index is equal to or greater than Count.1044        /// </exception>1045        /// <exception cref="ArgumentException">1046        /// value reference is null.1047        /// (or)1048        /// value is not of the correct generic type T for the buffer.1049        /// </exception>1050        object IList.this[int index]1051        {1052            get1053            {1054                return this[index];1055            }1056 1057            set1058            {1059                PSDataCollection<T>.VerifyValueType(value);1060                this[index] = (T)value;1061            }1062        }1063 1064        #endregion1065 1066        #region ICollection Overrides1067 1068        /// <summary>1069        /// Gets a value that indicates whether the buffer is synchronized.1070        /// </summary>1071        bool ICollection.IsSynchronized1072        {1073            get1074            {1075                return true;1076            }1077        }1078 1079        /// <summary>1080        /// Gets the object used to synchronize access to the thread-safe buffer.1081        /// </summary>1082        object ICollection.SyncRoot1083        {1084            get1085            {1086                return SyncObject;1087            }1088        }1089 1090        /// <summary>1091        /// Copies the elements of the collection to a specified array,1092        /// starting at a particular index.1093        /// </summary>1094        /// <param name="array">1095        /// The destination Array for the elements of type T copied1096        /// from the buffer.1097        /// </param>1098        /// <param name="index">1099        /// The zero-based index in the array at which copying begins.1100        /// </param>1101        /// <exception cref="ArgumentException">1102        /// array is multidimensional.1103        /// (or)1104        /// arrayIndex is equal to or greater than the length of array.1105        /// (or)1106        /// The number of elements in the source buffer is greater than the1107        /// available space from arrayIndex to the end of the destination array.1108        /// </exception>1109        /// <exception cref="ArgumentNullException">1110        /// array is a null reference1111        /// </exception>1112        /// <exception cref="ArgumentOutOfRangeException">1113        /// arrayIndex is less than 0.1114        /// </exception>1115        void ICollection.CopyTo(Array array, int index)1116        {1117            lock (SyncObject)1118            {1119                _data.CopyTo((T[])array, index);1120            }1121        }1122 1123        #endregion1124 1125        #region IEnumerable Overrides1126 1127        /// <summary>1128        /// Returns an enumerator that iterates through the buffer.1129        /// </summary>1130        /// <returns>1131        /// An IEnumerator for objects of the type stored in the buffer.1132        /// </returns>1133        IEnumerator IEnumerable.GetEnumerator()1134        {1135            return new PSDataCollectionEnumerator<T>(this, EnumeratorNeverBlocks);1136        }1137 1138        #endregion1139 1140        #region Streaming Behavior1141 1142        /// <summary>1143        /// Makes a shallow copy of all the elements currently in this collection1144        /// and clears them from this collection. This will not result in a blocking call.1145        ///1146        /// Calling this method might have side effects on the enumerator. When this1147        /// method is called, the behavior of the enumerator is not defined.1148        /// </summary>1149        /// <returns>1150        /// A new collection with a copy of all the elements in the current collection.1151        /// </returns>1152        public Collection<T> ReadAll()1153        {1154            return ReadAndRemove(0);1155        }1156 1157        /// <summary>1158        /// Makes a shallow copy of all the elements currently in this collection1159        /// and clears them from this collection. This will not result in a blocking call.1160        ///1161        /// Calling this method might have side effects on the enumerator. When this1162        /// method is called, the behavior of the enumerator is not defined.1163        /// </summary>1164        /// <returns>1165        /// A new collection with a copy of all the elements in the current collection.1166        /// </returns>1167        /// <param name="readCount">Maximum number of elements to read.</param>1168        internal Collection<T> ReadAndRemove(int readCount)1169        {1170            Dbg.Assert(_data != null, "Collection cannot be null");1171 1172            Dbg.Assert(readCount >= 0, "ReadCount cannot be negative");1173 1174            int resolvedReadCount = (readCount > 0 ? readCount : Int32.MaxValue);1175 1176            lock (SyncObject)1177            {1178                // Copy the elements into a new collection1179                // and clear.1180                Collection<T> result = new Collection<T>();1181 1182                for (int i = 0; i < resolvedReadCount; i++)1183                {1184                    if (_data.Count > 0)1185                    {1186                        result.Add(_data[0]);1187                        _data.RemoveAt(0);1188                    }1189                    else1190                    {1191                        break;1192                    }1193                }1194 1195                if (_readWaitHandle != null)1196                {1197                    if (_data.Count > 0 || !_isOpen)1198                    {1199                        // release all the waiting threads.1200                        _readWaitHandle.Set();

Showing the first 1,200 of 2122 lines. Download the file for the rest.