}
/// <summary>
- /// Initializes a block of memory at the given location with a given initial value
+ /// Initializes a block of memory at the given location with a given initial value
/// without assuming architecture dependent alignment of the address.
/// </summary>
[Intrinsic]
using Internal.Win32.SafeHandles;
//
-// A minimal version of RegistryKey that supports just what CoreLib needs.
+// A minimal version of RegistryKey that supports just what CoreLib needs.
//
-// Internal.Win32 namespace avoids confusion with the public standalone Microsoft.Win32.Registry implementation
+// Internal.Win32 namespace avoids confusion with the public standalone Microsoft.Win32.Registry implementation
// that lives in corefx.
//
namespace Internal.Win32
int errorCode = Interop.Advapi32.RegDeleteValue(_hkey, name);
//
- // From windows 2003 server, if the name is too long we will get error code ERROR_FILENAME_EXCED_RANGE
+ // From windows 2003 server, if the name is too long we will get error code ERROR_FILENAME_EXCED_RANGE
// This still means the name doesn't exist. We need to be consistent with previous OS.
//
if (errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND ||
int ret = Interop.Advapi32.RegOpenKeyEx(_hkey,
name,
0,
- writable ?
+ writable ?
Interop.Advapi32.RegistryOperations.KEY_READ | Interop.Advapi32.RegistryOperations.KEY_WRITE :
Interop.Advapi32.RegistryOperations.KEY_READ,
out SafeRegistryHandle result);
if (ret != 0)
{
// For stuff like ERROR_FILE_NOT_FOUND, we want to return null (data).
- // Some OS's returned ERROR_MORE_DATA even in success cases, so we
- // want to continue on through the function.
+ // Some OS's returned ERROR_MORE_DATA even in success cases, so we
+ // want to continue on through the function.
if (ret != Interop.Errors.ERROR_MORE_DATA)
return data;
}
}
else
{
- // in the very unlikely case the data is missing null termination,
+ // in the very unlikely case the data is missing null termination,
// pass in the whole char[] to prevent truncating a character
data = new string(blob);
}
}
else
{
- // in the very unlikely case the data is missing null termination,
+ // in the very unlikely case the data is missing null termination,
// pass in the whole char[] to prevent truncating a character
data = new string(blob);
}
// which obtains the raw errno that varies between unixes. The strong typing as an enum is meant to
// prevent confusing the two. Casting to or from int is suspect. Use GetLastErrorInfo() if you need to
// correlate these to the underlying platform values or obtain the corresponding error message.
- //
+ //
SUCCESS = 0,
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetTimeZoneDisplayName")]
internal static extern unsafe ResultCode GetTimeZoneDisplayName(
- string localeName,
- string timeZoneId,
- TimeZoneDisplayNameType type,
- char* result,
+ string localeName,
+ string timeZoneId,
+ TimeZoneDisplayNameType type,
+ char* result,
int resultLength);
}
}
{
/// <summary>
/// Takes a path to a symbolic link and attempts to place the link target path into the buffer. If the buffer is too
- /// small, the path will be truncated. No matter what, the buffer will not be null terminated.
+ /// small, the path will be truncated. No matter what, the buffer will not be null terminated.
/// </summary>
/// <param name="path">The path to the symlink</param>
/// <param name="buffer">The buffer to hold the output path</param>
}
/// <summary>
- /// Write a message to the system logger, which in turn writes the message to the system console, log files, etc.
+ /// Write a message to the system logger, which in turn writes the message to the system console, log files, etc.
/// See man 3 syslog for more info
/// </summary>
/// <param name="priority">
internal partial class Advapi32
{
/// <summary>
- /// Call the ETW native API EventWriteTransfer and checks for invalid argument error.
+ /// Call the ETW native API EventWriteTransfer and checks for invalid argument error.
/// The implementation of EventWriteTransfer on some older OSes (Windows 2008) does not accept null relatedActivityId.
/// So, for these cases we will retry the call with an empty Guid.
/// </summary>
internal const int REG_OPTION_NON_VOLATILE = 0x0000; // (default) keys are persisted beyond reboot/unload
internal const int REG_OPTION_VOLATILE = 0x0001; // All keys created by the function are volatile
internal const int REG_OPTION_CREATE_LINK = 0x0002; // They key is a symbolic link
- internal const int REG_OPTION_BACKUP_RESTORE = 0x0004; // Use SE_BACKUP_NAME process special privileges
+ internal const int REG_OPTION_BACKUP_RESTORE = 0x0004; // Use SE_BACKUP_NAME process special privileges
}
internal static class RegistryView
internal const int REG_QWORD = 11; // 64-bit number
}
}
-}
\ No newline at end of file
+}
internal const int BCRYPT_USE_SYSTEM_PREFERRED_RNG = 0x00000002;
[DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)]
- internal static extern unsafe NTSTATUS BCryptGenRandom(IntPtr hAlgorithm, byte* pbBuffer, int cbBuffer, int dwFlags);
+ internal static extern unsafe NTSTATUS BCryptGenRandom(IntPtr hAlgorithm, byte* pbBuffer, int cbBuffer, int dwFlags);
}
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
internal static extern bool EnumTimeFormatsEx(EnumTimeFormatsProcEx lpTimeFmtEnumProcEx, string lpLocaleName, uint dwFlags, void* lParam);
-
+
internal delegate BOOL EnumTimeFormatsProcEx(char* lpTimeFormatString, void* lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
internal static extern bool EnumCalendarInfoExEx(EnumCalendarInfoProcExEx pCalInfoEnumProcExEx, string lpLocaleName, uint Calendar, string? lpReserved, uint CalType, void* lParam);
-
+
internal delegate BOOL EnumCalendarInfoProcExEx(char* lpCalendarInfoString, uint Calendar, IntPtr lpReserved, void* lParam);
[StructLayout(LayoutKind.Sequential)]
internal int dwEffectiveId;
internal Guid guidCustomVersion;
}
-
+
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
internal static extern unsafe bool GetNLSVersionEx(int function, string localeName, NlsVersionInfoEx* lpVersionInformation);
}
{
[DllImport(Interop.Libraries.Kernel32, EntryPoint = "OpenSemaphoreW", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern SafeWaitHandle OpenSemaphore(uint desiredAccess, bool inheritHandle, string name);
-
+
[DllImport(Libraries.Kernel32, EntryPoint = "CreateSemaphoreExW", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern SafeWaitHandle CreateSemaphoreEx(IntPtr lpSecurityAttributes, int initialCount, int maximumCount, string? name, uint flags, uint desiredAccess);
{
internal partial class Kernel32
{
- // Note there are two different WriteFile prototypes - this is to use
- // the type system to force you to not trip across a "feature" in
+ // Note there are two different WriteFile prototypes - this is to use
+ // the type system to force you to not trip across a "feature" in
// Win32's async IO support. You can't do the following three things
- // simultaneously: overlapped IO, free the memory for the overlapped
+ // simultaneously: overlapped IO, free the memory for the overlapped
// struct in a callback (or an EndWrite method called by that callback),
// and pass in an address for the numBytesRead parameter.
{
internal partial class Kernel32
{
- // Note there are two different WriteFile prototypes - this is to use
- // the type system to force you to not trip across a "feature" in
+ // Note there are two different WriteFile prototypes - this is to use
+ // the type system to force you to not trip across a "feature" in
// Win32's async IO support. You can't do the following three things
- // simultaneously: overlapped IO, free the memory for the overlapped
+ // simultaneously: overlapped IO, free the memory for the overlapped
// struct in a callback (or an EndWrite method called by that callback),
// and pass in an address for the numBytesRead parameter.
[DllImport(Libraries.Kernel32, SetLastError = true)]
errorRewriter: e => (e.Error == Interop.Error.EISDIR) ? Interop.Error.EACCES.Info() : e);
}
- // Make sure it's not a directory; we do this after opening it once we have a file descriptor
+ // Make sure it's not a directory; we do this after opening it once we have a file descriptor
// to avoid race conditions.
Interop.Sys.FileStatus status;
if (Interop.Sys.FStat(handle, out status) != 0)
protected override bool ReleaseHandle()
{
- // When the SafeFileHandle was opened, we likely issued an flock on the created descriptor in order to add
+ // When the SafeFileHandle was opened, we likely issued an flock on the created descriptor in order to add
// an advisory lock. This lock should be removed via closing the file descriptor, but close can be
// interrupted, and we don't retry closes. As such, we could end up leaving the file locked,
// which could prevent subsequent usage of the file until this process dies. To avoid that, we proactively
return rt.CreateInstanceDefaultCtor(publicOnly: !nonPublic, skipCheckThis: false, fillCache: true, wrapExceptions: wrapExceptions);
throw new ArgumentException(SR.Arg_MustBeType, nameof(type));
- }
+ }
private static ObjectHandle? CreateInstanceInternal(string assemblyString,
string typeName,
/// null.</exception>
public AggregateException(string? message, IEnumerable<Exception> innerExceptions)
// If it's already an IList, pass that along (a defensive copy will be made in the delegated ctor). If it's null, just pass along
- // null typed correctly. Otherwise, create an IList from the enumerable and pass that along.
+ // null typed correctly. Otherwise, create an IList from the enumerable and pass that along.
: this(message, innerExceptions as IList<Exception> ?? (innerExceptions == null ? (List<Exception>)null! : new List<Exception>(innerExceptions)))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="AggregateException"/> class with a specified error
- /// message and references to the inner exception dispatch info objects that represent the cause of
+ /// message and references to the inner exception dispatch info objects that represent the cause of
/// this exception.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// null.</exception>
internal AggregateException(string message, IEnumerable<ExceptionDispatchInfo> innerExceptionInfos)
// If it's already an IList, pass that along (a defensive copy will be made in the delegated ctor). If it's null, just pass along
- // null typed correctly. Otherwise, create an IList from the enumerable and pass that along.
+ // null typed correctly. Otherwise, create an IList from the enumerable and pass that along.
: this(message, innerExceptionInfos as IList<ExceptionDispatchInfo> ??
(innerExceptionInfos == null ?
(List<ExceptionDispatchInfo>)null! :
}
/// <summary>
- /// Allocates a new aggregate exception with the specified message and list of inner
+ /// Allocates a new aggregate exception with the specified message and list of inner
/// exception dispatch info objects.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <summary>
/// This helper property is used by the DebuggerDisplay.
- ///
- /// Note that we don't want to remove this property and change the debugger display to {InnerExceptions.Count}
- /// because DebuggerDisplay should be a single property access or parameterless method call, so that the debugger
+ ///
+ /// Note that we don't want to remove this property and change the debugger display to {InnerExceptions.Count}
+ /// because DebuggerDisplay should be a single property access or parameterless method call, so that the debugger
/// can use a fast path without using the expression evaluator.
- ///
+ ///
/// See https://docs.microsoft.com/en-us/visualstudio/debugger/using-the-debuggerdisplay-attribute
/// </summary>
private int InnerExceptionCount
{
get
{
- // The value of APP_CONTEXT_BASE_DIRECTORY key has to be a string and it is not allowed to be any other type.
+ // The value of APP_CONTEXT_BASE_DIRECTORY key has to be a string and it is not allowed to be any other type.
// Otherwise the caller will get invalid cast exception
return (string?)GetData("APP_CONTEXT_BASE_DIRECTORY") ??
s_defaultBaseDirectory ?? (s_defaultBaseDirectory = GetBaseDirectoryCore());
public object? CreateInstanceAndUnwrap(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes)
{
- ObjectHandle? oh = CreateInstance(assemblyName,
- typeName,
- ignoreCase,
+ ObjectHandle? oh = CreateInstance(assemblyName,
+ typeName,
+ ignoreCase,
bindingAttr,
- binder,
- args,
- culture,
- activationAttributes);
+ binder,
+ args,
+ culture,
+ activationAttributes);
return oh?.Unwrap();
}
public object? CreateInstanceAndUnwrap(string assemblyName, string typeName, object?[]? activationAttributes)
{
- ObjectHandle? oh = CreateInstance(assemblyName, typeName, activationAttributes);
+ ObjectHandle? oh = CreateInstance(assemblyName, typeName, activationAttributes);
return oh?.Unwrap();
}
public object? CreateInstanceFromAndUnwrap(string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes)
{
- ObjectHandle? oh = CreateInstanceFrom(assemblyFile,
- typeName,
- ignoreCase,
+ ObjectHandle? oh = CreateInstanceFrom(assemblyFile,
+ typeName,
+ ignoreCase,
bindingAttr,
- binder,
- args,
- culture,
+ binder,
+ args,
+ culture,
activationAttributes);
return oh?.Unwrap();
}
public object? CreateInstanceFromAndUnwrap(string assemblyFile, string typeName, object?[]? activationAttributes)
{
- ObjectHandle? oh = CreateInstanceFrom(assemblyFile, typeName, activationAttributes);
+ ObjectHandle? oh = CreateInstanceFrom(assemblyFile, typeName, activationAttributes);
return oh?.Unwrap();
}
namespace System
{
- // The ApplicationException is the base class for nonfatal,
- // application errors that occur. These exceptions are generated
- // (i.e., thrown) by an application, not the Runtime. Applications that need
- // to create their own exceptions do so by extending this class.
- // ApplicationException extends but adds no new functionality to
+ // The ApplicationException is the base class for nonfatal,
+ // application errors that occur. These exceptions are generated
+ // (i.e., thrown) by an application, not the Runtime. Applications that need
+ // to create their own exceptions do so by extending this class.
+ // ApplicationException extends but adds no new functionality to
// RecoverableException.
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class ApplicationException : Exception
{
// Creates a new ApplicationException with its message string set to
- // the empty string, its HRESULT set to COR_E_APPLICATION,
- // and its ExceptionInfo reference set to null.
+ // the empty string, its HRESULT set to COR_E_APPLICATION,
+ // and its ExceptionInfo reference set to null.
public ApplicationException()
: base(SR.Arg_ApplicationException)
{
}
// Creates a new ApplicationException with its message string set to
- // message, its HRESULT set to COR_E_APPLICATION,
- // and its ExceptionInfo reference set to null.
- //
+ // message, its HRESULT set to COR_E_APPLICATION,
+ // and its ExceptionInfo reference set to null.
+ //
public ApplicationException(string? message)
: base(message)
{
namespace System
{
- // The ArgumentException is thrown when an argument does not meet
+ // The ArgumentException is thrown when an argument does not meet
// the contract of the method. Ideally it should give a meaningful error
// message describing what was wrong and which parameter is incorrect.
[Serializable]
{
private string? _paramName;
- // Creates a new ArgumentException with its message
- // string set to the empty string.
+ // Creates a new ArgumentException with its message
+ // string set to the empty string.
public ArgumentException()
: base(SR.Arg_ArgumentException)
{
HResult = HResults.COR_E_ARGUMENT;
}
- // Creates a new ArgumentException with its message
- // string set to message.
- //
+ // Creates a new ArgumentException with its message
+ // string set to message.
+ //
public ArgumentException(string? message)
: base(message)
{
get
{
SetMessageField();
-
+
string s = base.Message;
if (!string.IsNullOrEmpty(_paramName))
{
private void SetMessageField()
{
- if (_message == null && HResult == System.HResults.COR_E_ARGUMENT)
+ if (_message == null && HResult == System.HResults.COR_E_ARGUMENT)
{
_message = SR.Arg_ArgumentException;
}
}
-
+
public virtual string? ParamName
{
get { return _paramName; }
namespace System
{
- // The ArgumentException is thrown when an argument
+ // The ArgumentException is thrown when an argument
// is null when it shouldn't be.
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class ArgumentNullException : ArgumentException
{
- // Creates a new ArgumentNullException with its message
+ // Creates a new ArgumentNullException with its message
// string set to a default message explaining an argument was null.
public ArgumentNullException()
: base(SR.ArgumentNull_Generic)
namespace System
{
- // The ArgumentOutOfRangeException is thrown when an argument
+ // The ArgumentOutOfRangeException is thrown when an argument
// is outside the legal range for that argument.
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
{
private object? _actualValue;
- // Creates a new ArgumentOutOfRangeException with its message
+ // Creates a new ArgumentOutOfRangeException with its message
// string set to a default message explaining an argument was out of range.
public ArgumentOutOfRangeException()
: base(SR.Arg_ArgumentOutOfRangeException)
}
// Gets the value of the argument that caused the exception.
- // Note - we don't set this anywhere in the class libraries in
+ // Note - we don't set this anywhere in the class libraries in
// version 1, but it might come in handy for other developers who
// want to avoid sticking printf's in their code.
public virtual object? ActualValue
public class ArithmeticException : SystemException
{
// Creates a new ArithmeticException with its message string set to
- // the empty string, its HRESULT set to COR_E_ARITHMETIC,
- // and its ExceptionInfo reference set to null.
+ // the empty string, its HRESULT set to COR_E_ARITHMETIC,
+ // and its ExceptionInfo reference set to null.
public ArithmeticException()
: base(SR.Arg_ArithmeticException)
{
}
// Creates a new ArithmeticException with its message string set to
- // message, its HRESULT set to COR_E_ARITHMETIC,
- // and its ExceptionInfo reference set to null.
- //
+ // message, its HRESULT set to COR_E_ARITHMETIC,
+ // and its ExceptionInfo reference set to null.
+ //
public ArithmeticException(string? message)
: base(message)
{
// handling all the multiple dimension & bounds correctly.
// Think of it like an odometer in your car - we start with
// the last digit, increment it, and check for rollover. If
- // it rolls over, we set all digits to the right and including
+ // it rolls over, we set all digits to the right and including
// the current to the appropriate lower bound. Do these overflow
- // checks for each dimension, and if the most significant digit
+ // checks for each dimension, and if the most significant digit
// has rolled over it's upper bound, we're done.
//
int rank = array.Rank;
{
_index = -1;
}
- }
+ }
internal sealed class SZGenericArrayEnumerator<T> : IEnumerator<T>
{
// Number of elements in the Array.
int ICollection.Count { get { return Length; } }
- // Returns an object appropriate for synchronizing access to this
+ // Returns an object appropriate for synchronizing access to this
// Array.
public object SyncRoot { get { return this; } }
public bool IsFixedSize { get { return true; } }
// Is this Array synchronized (i.e., thread-safe)? If you want a synchronized
- // collection, you can use SyncRoot as an object to synchronize your
- // collection with. You could also call GetSynchronized()
+ // collection, you can use SyncRoot as an object to synchronize your
+ // collection with. You could also call GetSynchronized()
// to get a synchronized wrapper around the Array.
public bool IsSynchronized { get { return false; } }
}
// Make a new array which is a shallow copy of the original array.
- //
+ //
public object Clone()
{
return MemberwiseClone();
// integer. The bitwise complement operator (~) can be applied to a
// negative result to produce the index of the first element (if any) that
// is larger than the given search value.
- //
+ //
public static int BinarySearch(Array array, object? value)
{
if (array == null)
// integer. The bitwise complement operator (~) can be applied to a
// negative result to produce the index of the first element (if any) that
// is larger than the given search value.
- //
+ //
public static int BinarySearch(Array array, int index, int length, object? value)
{
return BinarySearch(array, index, length, value, null);
// interface, which in that case must be implemented by all elements of the
// array and the given search value. This method assumes that the array is
// already sorted; if this is not the case, the result will be incorrect.
- //
+ //
// The method returns the index of the given value in the array. If the
// array does not contain the given value, the method returns a negative
// integer. The bitwise complement operator (~) can be applied to a
// negative result to produce the index of the first element (if any) that
// is larger than the given search value.
- //
+ //
public static int BinarySearch(Array array, object? value, IComparer? comparer)
{
if (array == null)
// all elements of the array and the given search value. This method
// assumes that the array is already sorted; if this is not the case, the
// result will be incorrect.
- //
+ //
// The method returns the index of the given value in the array. If the
// array does not contain the given value, the method returns a negative
// integer. The bitwise complement operator (~) can be applied to a
// negative result to produce the index of the first element (if any) that
// is larger than the given search value.
- //
+ //
public static int BinarySearch(Array array, int index, int length, object? value, IComparer? comparer)
{
if (array == null)
{
while (lo <= hi)
{
- // i might overflow if lo and hi are both large positive numbers.
+ // i might overflow if lo and hi are both large positive numbers.
int i = GetMedian(lo, hi);
int c;
// CopyTo copies a collection into an Array, starting at a particular
// index into the array.
- //
+ //
// This method is to support the ICollection interface, and calls
// Array.Copy internally. If you aren't using ICollection explicitly,
// call Array.Copy to avoid an extra indirection.
- //
+ //
public void CopyTo(Array array, int index)
{
if (array != null && array.Rank != 1)
}
else
{
- // Make sure we're not out of range
+ // Make sure we're not out of range
if (startIndex < 0 || startIndex >= array.Length)
{
ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index();
// Returns the index of the first occurrence of a given value in an array.
// The array is searched forwards, and the elements of the array are
// compared to the given value using the Object.Equals method.
- //
+ //
public static int IndexOf(Array array, object? value)
{
if (array == null)
// startIndex and ending at the last element of the array. The
// elements of the array are compared to the given value using the
// Object.Equals method.
- //
+ //
public static int IndexOf(Array array, object? value, int startIndex)
{
if (array == null)
// startIndex and upto count elements. The
// elements of the array are compared to the given value using the
// Object.Equals method.
- //
+ //
public static int IndexOf(Array array, object? value, int startIndex, int count)
{
if (array == null)
// Returns the index of the last occurrence of a given value in an array.
// The array is searched backwards, and the elements of the array are
// compared to the given value using the Object.Equals method.
- //
+ //
public static int LastIndexOf(Array array, object? value)
{
if (array == null)
// an array. The array is searched backwards, starting at index
// startIndex and ending at index 0. The elements of the array are
// compared to the given value using the Object.Equals method.
- //
+ //
public static int LastIndexOf(Array array, object? value, int startIndex)
{
if (array == null)
// startIndex and counting uptocount elements. The elements of
// the array are compared to the given value using the Object.Equals
// method.
- //
+ //
public static int LastIndexOf(Array array, object? value, int startIndex, int count)
{
if (array == null)
return -1;
}
- // Make sure we're not out of range
+ // Make sure we're not out of range
if ((uint)startIndex >= (uint)array.Length)
{
ThrowHelper.ThrowStartIndexArgumentOutOfRange_ArgumentOutOfRange_Index();
// method, an element previously located at index i will now be
// located at index length - i - 1, where length is the
// length of the array.
- //
+ //
public static void Reverse(Array array)
{
if (array == null)
// which was previously located at index i will now be located at
// index index + (index + count - i - 1).
// Reliability note: This may fail because it may have to box objects.
- //
+ //
public static void Reverse(Array array, int index, int length)
{
if (array == null)
// Sorts the elements of an array. The sort compares the elements to each
// other using the IComparable interface, which must be implemented
// by all elements of the array.
- //
+ //
public static void Sort(Array array)
{
if (array == null)
// corresponding elements in the items array. The sort compares the
// keys to each other using the IComparable interface, which must be
// implemented by all elements of the keys array.
- //
+ //
public static void Sort(Array keys, Array? items)
{
if (keys == null)
// Sorts the elements in a section of an array. The sort compares the
// elements to each other using the IComparable interface, which
// must be implemented by all elements in the given section of the array.
- //
+ //
public static void Sort(Array array, int index, int length)
{
Sort(array, null, index, length, null);
// corresponding elements in the items array. The sort compares the
// keys to each other using the IComparable interface, which must be
// implemented by all elements of the keys array.
- //
+ //
public static void Sort(Array keys, Array? items, int index, int length)
{
Sort(keys, items, index, length, null);
// null, the elements are compared to each other using the
// IComparable interface, which in that case must be implemented by
// all elements of the array.
- //
+ //
public static void Sort(Array array, IComparer? comparer)
{
if (array == null)
// comparer is null, the elements are compared to each other using
// the IComparable interface, which in that case must be implemented
// by all elements of the keys array.
- //
+ //
public static void Sort(Array keys, Array? items, IComparer? comparer)
{
if (keys == null)
// comparer is null, the elements are compared to each other using
// the IComparable interface, which in that case must be implemented
// by all elements in the given section of the array.
- //
+ //
public static void Sort(Array array, int index, int length, IComparer? comparer)
{
Sort(array, null, index, length, comparer);
// comparer is null, the elements are compared to each other using
// the IComparable interface, which in that case must be implemented
// by all elements of the given section of the keys array.
- //
+ //
public static void Sort(Array keys, Array? items, int index, int length, IComparer? comparer)
{
if (keys == null)
{
// Note: users should make sure they copy the fields out of an ArraySegment onto their stack
// then validate that the fields describe valid bounds within the array. This must be done
- // because assignments to value types are not atomic, and also because one thread reading
+ // because assignments to value types are not atomic, and also because one thread reading
// three fields from an ArraySegment may not see the same ArraySegment from one call to another
- // (ie, users could assign a new value to the old location).
+ // (ie, users could assign a new value to the old location).
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public readonly struct ArraySegment<T> : IList<T>, IReadOnlyList<T>
public ArraySegment<T> Slice(int index)
{
ThrowInvalidOperationIfDefault();
-
+
if ((uint)index > (uint)_count)
{
ThrowHelper.ThrowArgumentOutOfRange_IndexException();
public class ArrayTypeMismatchException : SystemException
{
// Creates a new ArrayMismatchException with its message string set to
- // the empty string, its HRESULT set to COR_E_ARRAYTYPEMISMATCH,
- // and its ExceptionInfo reference set to null.
+ // the empty string, its HRESULT set to COR_E_ARRAYTYPEMISMATCH,
+ // and its ExceptionInfo reference set to null.
public ArrayTypeMismatchException()
: base(SR.Arg_ArrayTypeMismatchException)
{
}
// Creates a new ArrayMismatchException with its message string set to
- // message, its HRESULT set to COR_E_ARRAYTYPEMISMATCH,
- // and its ExceptionInfo reference set to null.
- //
+ // message, its HRESULT set to COR_E_ARRAYTYPEMISMATCH,
+ // and its ExceptionInfo reference set to null.
+ //
public ArrayTypeMismatchException(string? message)
: base(message)
{
{
object? fieldValue = fields[i].GetValue(this);
- // The hashcode of an array ignores the contents of the array, so it can produce
+ // The hashcode of an array ignores the contents of the array, so it can produce
// different hashcodes for arrays with the same contents.
// Since we do deep comparisons of arrays in Equals(), this means Equals and GetHashCode will
// be inconsistent for arrays. Therefore, we ignore hashes of arrays.
}
#endif
- // Compares values of custom-attribute fields.
+ // Compares values of custom-attribute fields.
private static bool AreFieldValuesEqual(object? thisValue, object? thatValue)
{
if (thisValue == null && thatValue == null)
return false;
}
- // Attributes can only contain single-dimension arrays, so we don't need to worry about
+ // Attributes can only contain single-dimension arrays, so we don't need to worry about
// multidimensional arrays.
Debug.Assert(thisValueArray.Rank == 1 && thatValueArray.Rank == 1);
for (int j = 0; j < thisValueArray.Length; j++)
}
else
{
- // An object of type Attribute will cause a stack overflow.
+ // An object of type Attribute will cause a stack overflow.
// However, this should never happen because custom attributes cannot contain values other than
// constants, single-dimensional arrays and typeof expressions.
Debug.Assert(!(thisValue is Attribute));
**
**
** Purpose: The class denotes how to specify the usage of an attribute
-**
+**
**
===========================================================*/
internal static readonly AttributeUsageAttribute Default = new AttributeUsageAttribute(AttributeTargets.All);
- //Constructors
+ //Constructors
public AttributeUsageAttribute(AttributeTargets validOn)
{
_attributeTarget = validOn;
**
** Purpose: Exception to an invalid dll or executable format.
**
-**
+**
===========================================================*/
using System.Globalization;
namespace System
{
// The BitConverter class contains methods for
- // converting an array of bytes to one of the base data
+ // converting an array of bytes to one of the base data
// types, as well as for converting a base data type to an
// array of bytes.
public static class BitConverter
return true;
}
- // Converts an int into an array of bytes with length
+ // Converts an int into an array of bytes with length
// four.
public static byte[] GetBytes(int value)
{
return true;
}
- // Converts a long into an array of bytes with length
+ // Converts a long into an array of bytes with length
// eight.
public static byte[] GetBytes(long value)
{
return true;
}
- // Converts a float into an array of bytes with length
+ // Converts a float into an array of bytes with length
// four.
public static byte[] GetBytes(float value)
{
return true;
}
- // Converts a double into an array of bytes with length
+ // Converts a double into an array of bytes with length
// eight.
public static byte[] GetBytes(double value)
{
return true;
}
- // Converts an array of bytes into a char.
+ // Converts an array of bytes into a char.
public static char ToChar(byte[] value, int startIndex) => unchecked((char)ToInt16(value, startIndex));
// Converts a Span into a char
return Unsafe.ReadUnaligned<char>(ref MemoryMarshal.GetReference(value));
}
- // Converts an array of bytes into a short.
+ // Converts an array of bytes into a short.
public static short ToInt16(byte[] value, int startIndex)
{
if (value == null)
return Unsafe.ReadUnaligned<short>(ref MemoryMarshal.GetReference(value));
}
- // Converts an array of bytes into an int.
+ // Converts an array of bytes into an int.
public static int ToInt32(byte[] value, int startIndex)
{
if (value == null)
return Unsafe.ReadUnaligned<int>(ref MemoryMarshal.GetReference(value));
}
- // Converts an array of bytes into a long.
+ // Converts an array of bytes into a long.
public static long ToInt64(byte[] value, int startIndex)
{
if (value == null)
}
// Converts an array of bytes into an ushort.
- //
+ //
[CLSCompliant(false)]
public static ushort ToUInt16(byte[] value, int startIndex) => unchecked((ushort)ToInt16(value, startIndex));
}
// Converts an array of bytes into an uint.
- //
+ //
[CLSCompliant(false)]
public static uint ToUInt32(byte[] value, int startIndex) => unchecked((uint)ToInt32(value, startIndex));
}
// Converts an array of bytes into an unsigned long.
- //
+ //
[CLSCompliant(false)]
public static ulong ToUInt64(byte[] value, int startIndex) => unchecked((ulong)ToInt64(value, startIndex));
return Unsafe.ReadUnaligned<ulong>(ref MemoryMarshal.GetReference(value));
}
- // Converts an array of bytes into a float.
+ // Converts an array of bytes into a float.
public static float ToSingle(byte[] value, int startIndex) => Int32BitsToSingle(ToInt32(value, startIndex));
// Converts a Span into a float
return Unsafe.ReadUnaligned<float>(ref MemoryMarshal.GetReference(value));
}
- // Converts an array of bytes into a double.
+ // Converts an array of bytes into a double.
public static double ToDouble(byte[] value, int startIndex) => Int64BitsToDouble(ToInt64(value, startIndex));
// Converts a Span into a double
return Unsafe.ReadUnaligned<double>(ref MemoryMarshal.GetReference(value));
}
- // Converts an array of bytes into a String.
+ // Converts an array of bytes into a String.
public static string ToString(byte[] value, int startIndex, int length)
{
if (value == null)
});
}
- // Converts an array of bytes into a String.
+ // Converts an array of bytes into a String.
public static string ToString(byte[] value)
{
if (value == null)
return ToString(value, 0, value.Length);
}
- // Converts an array of bytes into a String.
+ // Converts an array of bytes into a String.
public static string ToString(byte[] value, int startIndex)
{
if (value == null)
}
/*==================================ToBoolean===================================
- **Action: Convert an array of bytes to a boolean value. We treat this array
+ **Action: Convert an array of bytes to a boolean value. We treat this array
** as if the first 4 bytes were an Int4 an operate on this value.
**Returns: True if the Int4 value of the first 4 bytes is non-zero.
**Arguments: value -- The byte array
** startIndex -- The position within the array.
**Exceptions: See ToInt4.
==============================================================================*/
- // Converts an array of bytes into a boolean.
+ // Converts an array of bytes into a boolean.
public static bool ToBoolean(byte[] value, int startIndex)
{
if (value == null)
** Purpose: The boolean class serves as a wrapper for the primitive
** type boolean.
**
-**
+**
===========================================================*/
using System.Runtime.CompilerServices;
//
// The internal string representation of true.
- //
+ //
internal const string TrueLiteral = "True";
// The internal string representation of false.
- //
+ //
internal const string FalseLiteral = "False";
//
// The public string representation of true.
- //
+ //
public static readonly string TrueString = TrueLiteral;
// The public string representation of false.
- //
+ //
public static readonly string FalseString = FalseLiteral;
//
// indicates the relationship. For booleans, false sorts before true.
// null is considered to be less than any instance.
// If object is not of type boolean, this method throws an ArgumentException.
- //
+ //
// Returns a value less than zero if this object
- //
+ //
public int CompareTo(object? obj)
{
if (obj == null)
//
// Static Methods
- //
+ //
// Custom string compares for early application use by config switches, etc
- //
+ //
internal static bool IsTrueStringIgnoreCase(ReadOnlySpan<char> value)
{
return (value.Length == 4 &&
}
// Determines whether a String represents true or false.
- //
+ //
public static bool Parse(string value)
{
if (value == null) throw new ArgumentNullException(nameof(value));
TryParse(value, out bool result) ? result : throw new FormatException(SR.Format(SR.Format_BadBoolean, new string(value)));
// Determines whether a String represents true or false.
- //
+ //
public static bool TryParse(string? value, out bool result)
{
if (value == null)
//
// IConvertible implementation
- //
+ //
public TypeCode GetTypeCode()
{
SpanHelpers.ClearWithoutReferences(ref *dest, len);
}
- // The attributes on this method are chosen for best JIT performance.
+ // The attributes on this method are chosen for best JIT performance.
// Please do not edit unless intentional.
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
[CLSCompliant(false)]
Memmove((byte*)destination, (byte*)source, checked((nuint)sourceBytesToCopy));
}
- // The attributes on this method are chosen for best JIT performance.
+ // The attributes on this method are chosen for best JIT performance.
// Please do not edit unless intentional.
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
[CLSCompliant(false)]
{
Debug.Assert((srcIndex >= 0) && (destIndex >= 0) && (len >= 0), "Index and length must be non-negative!");
Debug.Assert(dest.Length - destIndex >= len, "not enough bytes in dest");
- // If dest has 0 elements, the fixed statement will throw an
+ // If dest has 0 elements, the fixed statement will throw an
// IndexOutOfRangeException. Special-case 0-byte copies.
if (len == 0)
return;
{
Debug.Assert((srcIndex >= 0) && (destIndex >= 0) && (len >= 0), "Index and length must be non-negative!");
Debug.Assert(src.Length - srcIndex >= len, "not enough bytes in src");
- // If dest has 0 elements, the fixed statement will throw an
+ // If dest has 0 elements, the fixed statement will throw an
// IndexOutOfRangeException. Special-case 0-byte copies.
if (len == 0)
return;
namespace System.Buffers
{
/// <summary>
- /// Provides a resource pool that enables reusing instances of type <see cref="T:T[]"/>.
+ /// Provides a resource pool that enables reusing instances of type <see cref="T:T[]"/>.
/// </summary>
/// <remarks>
/// <para>
/// </summary>
/// <remarks>
/// The shared pool provides a default implementation of <see cref="ArrayPool{T}"/>
- /// that's intended for general applicability. It maintains arrays of multiple sizes, and
- /// may hand back a larger array than was actually requested, but will never hand back a smaller
- /// array than was requested. Renting a buffer from it with <see cref="Rent"/> will result in an
- /// existing buffer being taken from the pool if an appropriate buffer is available or in a new
+ /// that's intended for general applicability. It maintains arrays of multiple sizes, and
+ /// may hand back a larger array than was actually requested, but will never hand back a smaller
+ /// array than was requested. Renting a buffer from it with <see cref="Rent"/> will result in an
+ /// existing buffer being taken from the pool if an appropriate buffer is available or in a new
/// buffer being allocated if one is not available.
/// byte[] and char[] are the most commonly pooled array types. For these we use a special pool type
/// optimized for very fast access speeds, at the expense of more memory consumption.
/// An <see cref="T:T[]"/> that is at least <paramref name="minimumLength"/> in length.
/// </returns>
/// <remarks>
- /// This buffer is loaned to the caller and should be returned to the same pool via
- /// <see cref="Return"/> so that it may be reused in subsequent usage of <see cref="Rent"/>.
- /// It is not a fatal error to not return a rented buffer, but failure to do so may lead to
+ /// This buffer is loaned to the caller and should be returned to the same pool via
+ /// <see cref="Return"/> so that it may be reused in subsequent usage of <see cref="Rent"/>.
+ /// It is not a fatal error to not return a rented buffer, but failure to do so may lead to
/// decreased application performance, as the pool may need to create a new buffer to replace
/// the one lost.
/// </remarks>
public abstract T[] Rent(int minimumLength);
/// <summary>
- /// Returns to the pool an array that was previously obtained via <see cref="Rent"/> on the same
+ /// Returns to the pool an array that was previously obtained via <see cref="Rent"/> on the same
/// <see cref="ArrayPool{T}"/> instance.
/// </summary>
/// <param name="array">
/// </param>
/// <param name="clearArray">
/// If <c>true</c> and if the pool will store the buffer to enable subsequent reuse, <see cref="Return"/>
- /// will clear <paramref name="array"/> of its contents so that a subsequent consumer via <see cref="Rent"/>
+ /// will clear <paramref name="array"/> of its contents so that a subsequent consumer via <see cref="Rent"/>
/// will not see the previous consumer's content. If <c>false</c> or if the pool will release the buffer,
/// the array's contents are left unchanged.
/// </param>
/// <remarks>
- /// Once a buffer has been returned to the pool, the caller gives up all ownership of the buffer
+ /// Once a buffer has been returned to the pool, the caller gives up all ownership of the buffer
/// and must not use it. The reference returned from a given call to <see cref="Rent"/> must only be
/// returned via <see cref="Return"/> once. The default <see cref="ArrayPool{T}"/>
/// may hold onto the returned buffer in order to rent it again, or it may release the returned buffer
/// This is a no-op and added only for consistency.
/// This allows the caller to read a struct of numeric primitives and reverse each field
/// rather than having to skip sbyte fields.
- /// </summary>
+ /// </summary>
[CLSCompliant(false)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static sbyte ReverseEndianness(sbyte value)
/// <summary>
/// Reverses a primitive value - performs an endianness swap
- /// </summary>
+ /// </summary>
[Intrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static short ReverseEndianness(short value) => (short)ReverseEndianness((ushort)value);
/// <summary>
/// Reverses a primitive value - performs an endianness swap
- /// </summary>
+ /// </summary>
[Intrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int ReverseEndianness(int value) => (int)ReverseEndianness((uint)value);
/// <summary>
/// Reverses a primitive value - performs an endianness swap
- /// </summary>
+ /// </summary>
[Intrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long ReverseEndianness(long value) => (long)ReverseEndianness((ulong)value);
/// This is a no-op and added only for consistency.
/// This allows the caller to read a struct of numeric primitives and reverse each field
/// rather than having to skip byte fields.
- /// </summary>
+ /// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static byte ReverseEndianness(byte value)
+ public static byte ReverseEndianness(byte value)
{
return value;
}
/// <summary>
/// Reverses a primitive value - performs an endianness swap
- /// </summary>
+ /// </summary>
[CLSCompliant(false)]
[Intrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
/// <summary>
/// Reverses a primitive value - performs an endianness swap
- /// </summary>
+ /// </summary>
[CLSCompliant(false)]
[Intrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
/// <summary>
/// Reverses a primitive value - performs an endianness swap
- /// </summary>
+ /// </summary>
[CLSCompliant(false)]
[Intrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
/// <param name="format">The standard format to use</param>
/// <returns>
/// true for success. "bytesWritten" contains the length of the formatted text in bytes.
- /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
+ /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
/// </returns>
/// <remarks>
/// Formats supported:
/// <param name="format">The standard format to use</param>
/// <returns>
/// true for success. "bytesWritten" contains the length of the formatted text in bytes.
- /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
+ /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
/// </returns>
/// <exceptions>
/// <remarks>
/// <param name="format">The standard format to use</param>
/// <returns>
/// true for success. "bytesWritten" contains the length of the formatted text in bytes.
- /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
+ /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
/// </returns>
/// <remarks>
/// Formats supported:
/// <param name="format">The standard format to use</param>
/// <returns>
/// true for success. "bytesWritten" contains the length of the formatted text in bytes.
- /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
+ /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
/// </returns>
/// <remarks>
/// Formats supported:
- /// G/g (default)
+ /// G/g (default)
/// F/f 12.45 Fixed point
/// E/e 1.245000e1 Exponential
/// </remarks>
/// <param name="format">The standard format to use</param>
/// <returns>
/// true for success. "bytesWritten" contains the length of the formatted text in bytes.
- /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
+ /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
/// </returns>
/// <remarks>
/// Formats supported:
- /// G/g (default)
+ /// G/g (default)
/// F/f 12.45 Fixed point
/// E/e 1.245000e1 Exponential
/// </remarks>
/// <param name="format">The standard format to use</param>
/// <returns>
/// true for success. "bytesWritten" contains the length of the formatted text in bytes.
- /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
+ /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
/// </returns>
/// <remarks>
/// Formats supported:
- /// G/g (default)
+ /// G/g (default)
/// F/f 12.45 Fixed point
/// E/e 1.245000e1 Exponential
/// </remarks>
/// <param name="format">The standard format to use</param>
/// <returns>
/// true for success. "bytesWritten" contains the length of the formatted text in bytes.
- /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
+ /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
/// </returns>
/// <remarks>
/// Formats supported:
// 1st byte: the ASCII byte to insert for the opening brace position (or 0 if no braces),
// 2nd byte: the ASCII byte to insert for the closing brace position (or 0 if no braces),
// 3rd byte: high bit set if dashes are to be inserted.
- //
+ //
// The reason for keeping a single flag instead of separate vars is that we can avoid register spillage
// as we build up the output value.
int flags;
/// <param name="format">The standard format to use</param>
/// <returns>
/// true for success. "bytesWritten" contains the length of the formatted text in bytes.
- /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
+ /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
/// </returns>
/// <remarks>
/// Formats supported:
/// G/g (default)
- /// D/d 32767
- /// N/n 32,767
+ /// D/d 32767
+ /// N/n 32,767
/// X/x 7fff
/// </remarks>
/// <exceptions>
/// <param name="format">The standard format to use</param>
/// <returns>
/// true for success. "bytesWritten" contains the length of the formatted text in bytes.
- /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
+ /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
/// </returns>
/// <remarks>
/// Formats supported:
/// G/g (default)
- /// D/d 32767
- /// N/n 32,767
+ /// D/d 32767
+ /// N/n 32,767
/// X/x 7fff
/// </remarks>
/// <exceptions>
/// <param name="format">The standard format to use</param>
/// <returns>
/// true for success. "bytesWritten" contains the length of the formatted text in bytes.
- /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
+ /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
/// </returns>
/// <remarks>
/// Formats supported:
/// G/g (default)
- /// D/d 32767
- /// N/n 32,767
+ /// D/d 32767
+ /// N/n 32,767
/// X/x 7fff
/// </remarks>
/// <exceptions>
/// <param name="format">The standard format to use</param>
/// <returns>
/// true for success. "bytesWritten" contains the length of the formatted text in bytes.
- /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
+ /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
/// </returns>
/// <remarks>
/// Formats supported:
/// G/g (default)
- /// D/d 32767
- /// N/n 32,767
+ /// D/d 32767
+ /// N/n 32,767
/// X/x 7fff
/// </remarks>
/// <exceptions>
/// <param name="format">The standard format to use</param>
/// <returns>
/// true for success. "bytesWritten" contains the length of the formatted text in bytes.
- /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
+ /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
/// </returns>
/// <remarks>
/// Formats supported:
/// G/g (default)
- /// D/d 32767
- /// N/n 32,767
+ /// D/d 32767
+ /// N/n 32,767
/// X/x 7fff
/// </remarks>
/// <exceptions>
/// <param name="format">The standard format to use</param>
/// <returns>
/// true for success. "bytesWritten" contains the length of the formatted text in bytes.
- /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
+ /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
/// </returns>
/// <remarks>
/// Formats supported:
/// G/g (default)
- /// D/d 32767
- /// N/n 32,767
+ /// D/d 32767
+ /// N/n 32,767
/// X/x 7fff
/// </remarks>
/// <exceptions>
/// <param name="format">The standard format to use</param>
/// <returns>
/// true for success. "bytesWritten" contains the length of the formatted text in bytes.
- /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
+ /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
/// </returns>
/// <remarks>
/// Formats supported:
/// G/g (default)
- /// D/d 32767
- /// N/n 32,767
+ /// D/d 32767
+ /// N/n 32,767
/// X/x 7fff
/// </remarks>
/// <exceptions>
/// <param name="format">The standard format to use</param>
/// <returns>
/// true for success. "bytesWritten" contains the length of the formatted text in bytes.
- /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
+ /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
/// </returns>
/// <remarks>
/// Formats supported:
/// G/g (default)
- /// D/d 32767
- /// N/n 32,767
+ /// D/d 32767
+ /// N/n 32,767
/// X/x 7fff
/// </remarks>
/// <exceptions>
/// <param name="format">The standard format to use</param>
/// <returns>
/// true for success. "bytesWritten" contains the length of the formatted text in bytes.
- /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
+ /// false if buffer was too short. Iteratively increase the size of the buffer and retry until it succeeds.
/// </returns>
/// <remarks>
/// Formats supported:
/// <param name="standardFormat">Expected format of the Utf8 string</param>
/// <returns>
/// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
- /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
+ /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
/// </returns>
/// <remarks>
/// Formats supported:
/// <param name="standardFormat">Expected format of the Utf8 string</param>
/// <returns>
/// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
- /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
+ /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
/// </returns>
/// <remarks>
/// Formats supported:
/// <param name="standardFormat">Expected format of the Utf8 string</param>
/// <returns>
/// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
- /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
+ /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
/// </returns>
/// <remarks>
/// Formats supported:
/// <param name="standardFormat">Expected format of the Utf8 string</param>
/// <returns>
/// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
- /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
+ /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
/// </returns>
/// <remarks>
/// Formats supported:
- /// G/g (default)
+ /// G/g (default)
/// F/f 12.45 Fixed point
/// E/e 1.245000e1 Exponential
/// </remarks>
/// <param name="standardFormat">Expected format of the Utf8 string</param>
/// <returns>
/// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
- /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
+ /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
/// </returns>
/// <remarks>
/// Formats supported:
- /// G/g (default)
+ /// G/g (default)
/// F/f 12.45 Fixed point
/// E/e 1.245000e1 Exponential
/// </remarks>
/// <param name="standardFormat">Expected format of the Utf8 string</param>
/// <returns>
/// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
- /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
+ /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
/// </returns>
/// <remarks>
/// Formats supported:
- /// G/g (default)
+ /// G/g (default)
/// F/f 12.45 Fixed point
/// E/e 1.245000e1 Exponential
/// </remarks>
// Assuming the text doesn't look like a normal floating point, we attempt to parse it as one the special floating point values.
//
private static bool TryParseAsSpecialFloatingPoint<T>(ReadOnlySpan<byte> source, T positiveInfinity, T negativeInfinity, T nan, out T value, out int bytesConsumed) where T : struct
- {
+ {
int srcIndex = 0;
int remaining = source.Length;
bool isNegative = false;
/// <param name="standardFormat">Expected format of the Utf8 string</param>
/// <returns>
/// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
- /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
+ /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
/// </returns>
/// <remarks>
/// Formats supported:
int answer;
// Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior with the classic parse routines
- // (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
+ // (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
// one digit after the decimal point.)
if (c == Utf8Constants.Period)
goto FractionalPartWithoutLeadingDigits;
int answer;
// Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior with the classic parse routines
- // (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
+ // (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
// one digit after the decimal point.)
if (c == Utf8Constants.Period)
goto FractionalPartWithoutLeadingDigits;
int answer;
// Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior with the classic parse routines
- // (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
+ // (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
// one digit after the decimal point.)
if (c == Utf8Constants.Period)
goto FractionalPartWithoutLeadingDigits;
long answer;
// Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior with the classic parse routines
- // (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
+ // (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
// one digit after the decimal point.)
if (c == Utf8Constants.Period)
goto FractionalPartWithoutLeadingDigits;
/// <param name="standardFormat">Expected format of the Utf8 string</param>
/// <returns>
/// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
- /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
+ /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
/// </returns>
/// <remarks>
/// Formats supported:
/// G/g (default)
- /// D/d 32767
- /// N/n 32,767
+ /// D/d 32767
+ /// N/n 32,767
/// X/x 7fff
/// </remarks>
/// <exceptions>
/// <param name="standardFormat">Expected format of the Utf8 string</param>
/// <returns>
/// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
- /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
+ /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
/// </returns>
/// <remarks>
/// Formats supported:
/// G/g (default)
- /// D/d 32767
- /// N/n 32,767
+ /// D/d 32767
+ /// N/n 32,767
/// X/x 7fff
/// </remarks>
/// <exceptions>
/// <param name="standardFormat">Expected format of the Utf8 string</param>
/// <returns>
/// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
- /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
+ /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
/// </returns>
/// <remarks>
/// Formats supported:
/// G/g (default)
- /// D/d 32767
- /// N/n 32,767
+ /// D/d 32767
+ /// N/n 32,767
/// X/x 7fff
/// </remarks>
/// <exceptions>
/// <param name="standardFormat">Expected format of the Utf8 string</param>
/// <returns>
/// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
- /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
+ /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
/// </returns>
/// <remarks>
/// Formats supported:
/// G/g (default)
- /// D/d 32767
- /// N/n 32,767
+ /// D/d 32767
+ /// N/n 32,767
/// X/x 7fff
/// </remarks>
/// <exceptions>
int answer;
// Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior with the classic parse routines
- // (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
+ // (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
// one digit after the decimal point.)
if (c == Utf8Constants.Period)
goto FractionalPartWithoutLeadingDigits;
int answer;
// Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior with the classic parse routines
- // (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
+ // (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
// one digit after the decimal point.)
if (c == Utf8Constants.Period)
goto FractionalPartWithoutLeadingDigits;
int answer;
// Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior with the classic parse routines
- // (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
+ // (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
// one digit after the decimal point.)
if (c == Utf8Constants.Period)
goto FractionalPartWithoutLeadingDigits;
long answer;
// Handle the first digit (or period) as a special case. This ensures some compatible edge-case behavior with the classic parse routines
- // (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
+ // (at least one digit must precede any commas, and a string without any digits prior to the decimal point must have at least
// one digit after the decimal point.)
if (c == Utf8Constants.Period)
goto FractionalPartWithoutLeadingDigits;
/// <param name="standardFormat">Expected format of the Utf8 string</param>
/// <returns>
/// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
- /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
+ /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
/// </returns>
/// <remarks>
/// Formats supported:
/// G/g (default)
- /// D/d 32767
- /// N/n 32,767
+ /// D/d 32767
+ /// N/n 32,767
/// X/x 7fff
/// </remarks>
/// <exceptions>
/// <param name="standardFormat">Expected format of the Utf8 string</param>
/// <returns>
/// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
- /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
+ /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
/// </returns>
/// <remarks>
/// Formats supported:
/// G/g (default)
- /// D/d 32767
- /// N/n 32,767
+ /// D/d 32767
+ /// N/n 32,767
/// X/x 7fff
/// </remarks>
/// <exceptions>
/// <param name="standardFormat">Expected format of the Utf8 string</param>
/// <returns>
/// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
- /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
+ /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
/// </returns>
/// <remarks>
/// Formats supported:
/// G/g (default)
- /// D/d 32767
- /// N/n 32,767
+ /// D/d 32767
+ /// N/n 32,767
/// X/x 7fff
/// </remarks>
/// <exceptions>
/// <param name="standardFormat">Expected format of the Utf8 string</param>
/// <returns>
/// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
- /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
+ /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
/// </returns>
/// <remarks>
/// Formats supported:
/// G/g (default)
- /// D/d 32767
- /// N/n 32,767
+ /// D/d 32767
+ /// N/n 32,767
/// X/x 7fff
/// </remarks>
/// <exceptions>
if (number.Scale < int.MinValue + (long)absoluteExponent)
{
// A scale underflow means all non-zero digits are all so far to the right of the decimal point, no
- // number format we have will be able to see them. Just pin the scale at the absolute minimum
+ // number format we have will be able to see them. Just pin the scale at the absolute minimum
// and let the converter produce a 0 with the max precision available for that type.
number.Scale = int.MinValue;
}
if (number.Scale > int.MaxValue - (long)absoluteExponent)
{
// A scale overflow means all non-zero digits are all so far to the right of the decimal point, no
- // number format we have will be able to see them. Just pin the scale at the absolute maximum
+ // number format we have will be able to see them. Just pin the scale at the absolute maximum
// and let the converter produce a 0 with the max precision available for that type.
number.Scale = int.MaxValue;
}
/// <param name="standardFormat">Expected format of the Utf8 string</param>
/// <returns>
/// true for success. "bytesConsumed" contains the length in bytes of the substring that was parsed.
- /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
+ /// false if the string was not syntactically valid or an overflow or underflow occurred. "bytesConsumed" is set to 0.
/// </returns>
/// <remarks>
/// Formats supported:
namespace System
{
// ByReference<T> is meant to be used to represent "ref T" fields. It is working
- // around lack of first class support for byref fields in C# and IL. The JIT and
+ // around lack of first class support for byref fields in C# and IL. The JIT and
// type loader has special handling for it that turns it into a thin wrapper around ref T.
[NonVersionable]
internal readonly ref struct ByReference<T>
[Intrinsic]
public ByReference(ref T value)
{
- // Implemented as a JIT intrinsic - This default implementation is for
+ // Implemented as a JIT intrinsic - This default implementation is for
// completeness and to provide a concrete error if called via reflection
// or if intrinsic is missed.
throw new PlatformNotSupportedException();
[Intrinsic]
get
{
- // Implemented as a JIT intrinsic - This default implementation is for
+ // Implemented as a JIT intrinsic - This default implementation is for
// completeness and to provide a concrete error if called via reflection
// or if the intrinsic is missed.
throw new PlatformNotSupportedException();
// Compares this object to another object, returning an integer that
- // indicates the relationship.
+ // indicates the relationship.
// Returns a value less than zero if this object
// null is considered to be less than any instance.
// If object is not of type byte, this method throws an ArgumentException.
- //
+ //
public int CompareTo(object? value)
{
if (value == null)
}
// Parses an unsigned byte from a String in the given style. If
- // a NumberFormatInfo isn't specified, the current culture's
+ // a NumberFormatInfo isn't specified, the current culture's
// NumberFormatInfo is assumed.
public static byte Parse(string s, NumberStyles style, IFormatProvider? provider)
{
//
// IConvertible implementation
- //
+ //
public TypeCode GetTypeCode()
{
return TypeCode.Byte;
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public readonly struct Char : IComparable, IComparable<char>, IEquatable<char>, IConvertible
{
//
return (uint)ch <= '\x007f';
}
- // Return the Unicode category for Unicode character <= 0x00ff.
+ // Return the Unicode category for Unicode character <= 0x00ff.
private static UnicodeCategory GetLatin1UnicodeCategory(char ch)
{
Debug.Assert(IsLatin1(ch), "char.GetLatin1UnicodeCategory(): ch should be <= 007f");
}
// Compares this object to another object, returning an integer that
- // indicates the relationship.
+ // indicates the relationship.
// Returns a value less than zero if this object
// null is considered to be less than any instance.
// If object is not of type Char, this method throws an ArgumentException.
//
// IConvertible implementation
- //
+ //
public TypeCode GetTypeCode()
{
return TypeCode.Char;
/*=============================ConvertToUtf32===================================
- ** Convert a surrogate pair to UTF32 value
+ ** Convert a surrogate pair to UTF32 value
==============================================================================*/
public static int ConvertToUtf32(char highSurrogate, char lowSurrogate)
}
/*=============================ConvertToUtf32===================================
- ** Convert a character or a surrogate pair starting at index of the specified string
+ ** Convert a character or a surrogate pair starting at index of the specified string
** to UTF32 value.
** The char pointed by index should be a surrogate pair or a BMP character.
** This method throws if a high-surrogate is not followed by a low surrogate.
// of the internal array. As elements are added to a ArrayList, the capacity
// of the ArrayList is automatically increased as required by reallocating the
// internal array.
- //
+ //
[DebuggerTypeProxy(typeof(System.Collections.ArrayList.ArrayListDebugView))]
[DebuggerDisplay("Count = {Count}")]
[Serializable]
// Constructs a ArrayList with a given initial capacity. The list is
// initially empty, but will have room for the given number of elements
// before any reallocations are required.
- //
+ //
public ArrayList(int capacity)
{
if (capacity < 0) throw new ArgumentOutOfRangeException(nameof(capacity), SR.Format(SR.ArgumentOutOfRange_MustBeNonNegNum, nameof(capacity)));
// Constructs a ArrayList, copying the contents of the given collection. The
// size and capacity of the new list will both be equal to the size of the
// given collection.
- //
+ //
public ArrayList(ICollection c)
{
if (c == null)
}
// Gets and sets the capacity of this list. The capacity is the size of
- // the internal array used to hold items. When set, the internal
+ // the internal array used to hold items. When set, the internal
// array of the list is reallocated to the given capacity.
- //
+ //
public virtual int Capacity
{
get
public virtual object SyncRoot => this;
// Sets or Gets the element at the given index.
- //
+ //
public virtual object? this[int index]
{
get
// is larger than the given search value. This is also the index at which
// the search value should be inserted into the list in order for the list
// to remain sorted.
- //
+ //
// The method uses the Array.BinarySearch method to perform the
// search.
- //
+ //
public virtual int BinarySearch(int index, int count, object? value, IComparer? comparer)
{
if (index < 0)
}
// Clones this ArrayList, doing a shallow copy. (A copy is made of all
- // Object references in the ArrayList, but the Objects pointed to
+ // Object references in the ArrayList, but the Objects pointed to
// are not cloned).
public virtual object Clone()
{
}
}
- // Copies this ArrayList into array, which must be of a
- // compatible array type.
+ // Copies this ArrayList into array, which must be of a
+ // compatible array type.
//
public virtual void CopyTo(Array array)
{
CopyTo(array, 0);
}
- // Copies this ArrayList into array, which must be of a
- // compatible array type.
+ // Copies this ArrayList into array, which must be of a
+ // compatible array type.
//
public virtual void CopyTo(Array array, int arrayIndex)
{
}
// Copies a section of this list to the given array at the given index.
- //
+ //
// The method uses the Array.Copy method to copy the elements.
- //
+ //
public virtual void CopyTo(int index, Array array, int arrayIndex, int count)
{
if (_size - index < count)
}
// Returns an enumerator for this list with the given
- // permission for removal of elements. If modifications made to the list
- // while an enumeration is in progress, the MoveNext and
+ // permission for removal of elements. If modifications made to the list
+ // while an enumeration is in progress, the MoveNext and
// GetObject methods of the enumerator will throw an exception.
//
public virtual IEnumerator GetEnumerator()
}
// Returns an enumerator for a section of this list with the given
- // permission for removal of elements. If modifications made to the list
- // while an enumeration is in progress, the MoveNext and
+ // permission for removal of elements. If modifications made to the list
+ // while an enumeration is in progress, the MoveNext and
// GetObject methods of the enumerator will throw an exception.
//
public virtual IEnumerator GetEnumerator(int index, int count)
// this list. The list is searched forwards from beginning to end.
// The elements of the list are compared to the given value using the
// Object.Equals method.
- //
+ //
// This method uses the Array.IndexOf method to perform the
// search.
- //
+ //
public virtual int IndexOf(object? value)
{
return Array.IndexOf((Array)_items, value, 0, _size);
// startIndex and ending at count number of elements. The
// elements of the list are compared to the given value using the
// Object.Equals method.
- //
+ //
// This method uses the Array.IndexOf method to perform the
// search.
- //
+ //
public virtual int IndexOf(object? value, int startIndex)
{
if (startIndex > _size)
// startIndex and up to count number of elements. The
// elements of the list are compared to the given value using the
// Object.Equals method.
- //
+ //
// This method uses the Array.IndexOf method to perform the
// search.
- //
+ //
public virtual int IndexOf(object? value, int startIndex, int count)
{
if (startIndex > _size)
// Inserts an element into this list at a given index. The size of the list
// is increased by one. If required, the capacity of the list is doubled
// before inserting the new element.
- //
+ //
public virtual void Insert(int index, object? value)
{
// Note that insertions at the end are legal.
}
// Returns the index of the last occurrence of a given value in a range of
- // this list. The list is searched backwards, starting at the end
- // and ending at the first element in the list. The elements of the list
+ // this list. The list is searched backwards, starting at the end
+ // and ending at the first element in the list. The elements of the list
// are compared to the given value using the Object.Equals method.
- //
+ //
// This method uses the Array.LastIndexOf method to perform the
// search.
- //
+ //
public virtual int LastIndexOf(object? value)
{
return LastIndexOf(value, _size - 1, _size);
// Returns the index of the last occurrence of a given value in a range of
// this list. The list is searched backwards, starting at index
- // startIndex and ending at the first element in the list. The
- // elements of the list are compared to the given value using the
+ // startIndex and ending at the first element in the list. The
+ // elements of the list are compared to the given value using the
// Object.Equals method.
- //
+ //
// This method uses the Array.LastIndexOf method to perform the
// search.
- //
+ //
public virtual int LastIndexOf(object? value, int startIndex)
{
if (startIndex >= _size)
// startIndex and up to count elements. The elements of
// the list are compared to the given value using the Object.Equals
// method.
- //
+ //
// This method uses the Array.LastIndexOf method to perform the
// search.
- //
+ //
public virtual int LastIndexOf(object? value, int startIndex, int count)
{
if (Count != 0 && (startIndex < 0 || count < 0))
// Removes the element at the given index. The size of the list is
// decreased by one.
- //
+ //
public virtual void Remove(object? obj)
{
int index = IndexOf(obj);
// Removes the element at the given index. The size of the list is
// decreased by one.
- //
+ //
public virtual void RemoveAt(int index)
{
if (index < 0 || index >= _size) throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index);
}
// Removes a range of elements from this list.
- //
+ //
public virtual void RemoveRange(int index, int count)
{
if (index < 0)
// method, an element in the range given by index and count
// which was previously located at index i will now be located at
// index index + (index + count - i - 1).
- //
+ //
// This method uses the Array.Reverse method to reverse the
// elements.
- //
+ //
public virtual void Reverse(int index, int count)
{
if (index < 0)
return new Range(this, index, count);
}
- // Sorts the elements in this list. Uses the default comparer and
+ // Sorts the elements in this list. Uses the default comparer and
// Array.Sort.
public virtual void Sort()
{
// comparer is null, the elements are compared to each other using
// the IComparable interface, which in that case must be implemented by all
// elements of the list.
- //
+ //
// This method uses the Array.Sort method to sort the elements.
- //
+ //
public virtual void Sort(int index, int count, IComparer? comparer)
{
if (index < 0)
return array;
}
- // ToArray returns a new array of a particular type containing the contents
+ // ToArray returns a new array of a particular type containing the contents
// of the ArrayList. This requires copying the ArrayList and potentially
// downcasting all elements. This copy may fail and is an O(n) operation.
// Internally, this implementation calls Array.Copy.
// new elements will be added to the list. To completely clear a list and
// release all memory referenced by the list, execute the following
// statements:
- //
+ //
// list.Clear();
// list.TrimToSize();
- //
+ //
public virtual void TrimToSize()
{
Capacity = _size;
ArrayList? al = _list as ArrayList;
if (al != null)
{
- // We need to special case ArrayList.
+ // We need to special case ArrayList.
// When c is a range of _list, we need to handle this in a special way.
// See ArrayList.InsertRange for details.
al.InsertRange(index, c);
InternalUpdateRange();
// No need to call _bastList.RemoveRange if count is 0.
- // In addition, _baseList won't change the version number if count is 0.
+ // In addition, _baseList won't change the version number if count is 0.
if (count > 0)
{
_baseList.RemoveRange(_baseIndex + index, count);
// If a implements IComparable, a.CompareTo(b) is returned.
// If a doesn't implement IComparable and b does, -(b.CompareTo(a)) is returned.
// Otherwise an exception is thrown.
- //
+ //
public int Compare(object? a, object? b)
{
if (a == b) return 0;
/// cref="ConcurrentQueue{T}"/>.</returns>
/// <remarks>
/// The enumeration represents a moment-in-time snapshot of the contents
- /// of the queue. It does not reflect any updates to the collection after
+ /// of the queue. It does not reflect any updates to the collection after
/// <see cref="GetEnumerator"/> was called. The enumerator is safe to use
/// concurrently with reads from and writes to the queue.
/// </remarks>
/// <summary>
/// Provides a multi-producer, multi-consumer thread-safe bounded segment. When the queue is full,
/// enqueues fail and return false. When the queue is empty, dequeues fail and return null.
- /// These segments are linked together to form the unbounded <see cref="ConcurrentQueue{T}"/>.
+ /// These segments are linked together to form the unbounded <see cref="ConcurrentQueue{T}"/>.
/// </summary>
[DebuggerDisplay("Capacity = {Capacity}")]
internal sealed class ConcurrentQueueSegment<T>
public bool TryDequeue([MaybeNullWhen(false)] out T item)
{
Slot[] slots = _slots;
-
+
// Loop in case of contention...
var spinner = new SpinWait();
while (true)
/*============================================================
**
**
-**
+**
**
**
** Purpose: class to sort arrays
**
-**
+**
===========================================================*/
using System.Diagnostics;
TValue value = values[a];
values[a] = values[b];
- values[b] = value;
+ values[b] = value;
}
}
}
TValue v = values[i];
values[i] = values[j];
- values[j] = v;
+ values[j] = v;
}
}
TValue value = values[a];
values[a] = values[b];
- values[b] = value;
+ values[b] = value;
}
}
}
namespace System.Collections.Generic
{
[Serializable]
- [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public abstract partial class Comparer<T> : IComparer, IComparer<T>
{
// public static Comparer<T> Default is runtime-specific
return 0;
}
- // Equals method for the comparer itself.
+ // Equals method for the comparer itself.
public override bool Equals(object? obj) =>
obj != null && GetType() == obj.GetType();
return 0;
}
- // Equals method for the comparer itself.
+ // Equals method for the comparer itself.
public override bool Equals(object? obj) =>
obj != null && GetType() == obj.GetType();
return System.Collections.Comparer.Default.Compare(x, y);
}
- // Equals method for the comparer itself.
+ // Equals method for the comparer itself.
public override bool Equals(object? obj) =>
obj != null && GetType() == obj.GetType();
// public override int Compare(T x, T y) is runtime-specific
- // Equals method for the comparer itself.
+ // Equals method for the comparer itself.
public override bool Equals(object? obj) =>
obj != null && GetType() == obj.GetType();
if (siInfo == null)
{
- // We can return immediately if this function is called twice.
+ // We can return immediately if this function is called twice.
// Note we remove the serialization info from the table at the end of this method.
return;
}
/// <summary>
/// Sets the capacity of this dictionary to what it would be if it had been originally initialized with all its entries
- ///
- /// This method can be used to minimize the memory overhead
- /// once it is known that no new elements will be added.
- ///
+ ///
+ /// This method can be used to minimize the memory overhead
+ /// once it is known that no new elements will be added.
+ ///
/// To allocate minimum size storage array, execute the following statements:
- ///
+ ///
/// dictionary.Clear();
/// dictionary.TrimExcess();
/// </summary>
/// <summary>
/// Sets the capacity of this dictionary to hold up 'capacity' entries without any further expansion of its backing storage
- ///
- /// This method can be used to minimize the memory overhead
- /// once it is known that no new elements will be added.
+ ///
+ /// This method can be used to minimize the memory overhead
+ /// once it is known that no new elements will be added.
/// </summary>
public void TrimExcess(int capacity)
{
namespace System.Collections.Generic
{
[Serializable]
- [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public abstract partial class EqualityComparer<T> : IEqualityComparer, IEqualityComparer<T>
{
// public static EqualityComparer<T> Default is runtime-specific
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
- // For back-compat we need to serialize the comparers for enums with underlying types other than int as ObjectEqualityComparer
+ // For back-compat we need to serialize the comparers for enums with underlying types other than int as ObjectEqualityComparer
if (Type.GetTypeCode(Enum.GetUnderlyingType(typeof(T))) != TypeCode.Int32) {
info.SetType(typeof(ObjectEqualityComparer<T>));
}
namespace System.Collections.Generic
{
- // Base interface for all collections, defining enumerators, size, and
+ // Base interface for all collections, defining enumerators, size, and
// synchronization methods.
public interface ICollection<T> : IEnumerable<T>
{
- // Number of items in the collections.
+ // Number of items in the collections.
int Count { get; }
bool IsReadOnly { get; }
// CopyTo copies a collection into an Array, starting at a particular
// index into the array.
- //
+ //
void CopyTo(T[] array, int arrayIndex);
//void CopyTo(int sourceIndex, T[] destinationArray, int destinationIndex, int count);
namespace System.Collections.Generic
{
- // The generic IComparer interface implements a method that compares
- // two objects. It is used in conjunction with the Sort and
+ // The generic IComparer interface implements a method that compares
+ // two objects. It is used in conjunction with the Sort and
// BinarySearch methods on the Array, List, and SortedList classes.
public interface IComparer<in T>
{
// Compares two objects. An implementation of this method must return a
// value less than zero if x is less than y, zero if x is equal to y, or a
// value greater than zero if x is greater than y.
- //
+ //
int Compare([AllowNull] T x, [AllowNull] T y);
}
}
public interface IDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>> where TKey : notnull
{
// Interfaces are not serializable
- // The Item property provides methods to read and edit entries
+ // The Item property provides methods to read and edit entries
// in the Dictionary.
TValue this[TKey key]
{
bool ContainsKey(TKey key);
// Adds a key-value pair to the dictionary.
- //
+ //
void Add(TKey key, TValue value);
// Removes a particular key from the dictionary.
// Returns the current element of the enumeration. The returned value is
// undefined before the first call to MoveNext and following a
// call to MoveNext that returned false. Multiple calls to
- // GetCurrent with no intervening calls to MoveNext
+ // GetCurrent with no intervening calls to MoveNext
// will return the same object.
new T Current
{
{
// The generic IEqualityComparer interface implements methods to if check two objects are equal
// and generate Hashcode for an object.
- // It is use in Dictionary class.
+ // It is use in Dictionary class.
public interface IEqualityComparer<in T>
{
bool Equals([AllowNull] T x, [AllowNull] T y);
int GetHashCode([DisallowNull] T obj);
}
}
-
{
// An IList is an ordered collection of objects. The exact ordering
// is up to the implementation of the list, ranging from a sorted
- // order to insertion order.
+ // order to insertion order.
public interface IList<T> : ICollection<T>
{
// The Item property provides methods to read and edit entries in the List.
int IndexOf(T item);
// Inserts value into the list at position index.
- // index must be non-negative and less than or equal to the
+ // index must be non-negative and less than or equal to the
// number of elements in the list. If index equals the number
// of items in the list, then value is appended to the end.
void Insert(int index, T item);
// of the internal array. As elements are added to a List, the capacity
// of the List is automatically increased as required by reallocating the
// internal array.
- //
+ //
[DebuggerTypeProxy(typeof(ICollectionDebugView<>))]
[DebuggerDisplay("Count = {Count}")]
[Serializable]
// Constructs a List with a given initial capacity. The list is
// initially empty, but will have room for the given number of elements
// before any reallocations are required.
- //
+ //
public List(int capacity)
{
if (capacity < 0)
// Constructs a List, copying the contents of the given collection. The
// size and capacity of the new list will both be equal to the size of the
// given collection.
- //
+ //
public List(IEnumerable<T> collection)
{
if (collection == null)
}
// Gets and sets the capacity of this list. The capacity is the size of
- // the internal array used to hold items. When set, the internal
+ // the internal array used to hold items. When set, the internal
// array of the list is reallocated to the given capacity.
- //
+ //
public int Capacity
{
get
private static bool IsCompatibleObject(object? value)
{
// Non-null values are fine. Only accept nulls if T is a class or Nullable<U>.
- // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
+ // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
return ((value is T) || (value == null && default(T)! == null)); // default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
}
// is larger than the given search value. This is also the index at which
// the search value should be inserted into the list in order for the list
// to remain sorted.
- //
+ //
// The method uses the Array.BinarySearch method to perform the
// search.
- //
+ //
public int BinarySearch(int index, int count, T item, IComparer<T>? comparer)
{
if (index < 0)
return list;
}
- // Copies this List into array, which must be of a
- // compatible array type.
+ // Copies this List into array, which must be of a
+ // compatible array type.
public void CopyTo(T[] array)
=> CopyTo(array, 0);
- // Copies this List into array, which must be of a
- // compatible array type.
+ // Copies this List into array, which must be of a
+ // compatible array type.
void ICollection.CopyTo(Array array, int arrayIndex)
{
if ((array != null) && (array.Rank != 1))
}
// Copies a section of this list to the given array at the given index.
- //
+ //
// The method uses the Array.Copy method to copy the elements.
- //
+ //
public void CopyTo(int index, T[] array, int arrayIndex, int count)
{
if (_size - index < count)
}
// Returns an enumerator for this list with the given
- // permission for removal of elements. If modifications made to the list
- // while an enumeration is in progress, the MoveNext and
+ // permission for removal of elements. If modifications made to the list
+ // while an enumeration is in progress, the MoveNext and
// GetObject methods of the enumerator will throw an exception.
//
public Enumerator GetEnumerator()
// this list. The list is searched forwards from beginning to end.
// The elements of the list are compared to the given value using the
// Object.Equals method.
- //
+ //
// This method uses the Array.IndexOf method to perform the
// search.
- //
+ //
public int IndexOf(T item)
=> Array.IndexOf(_items, item, 0, _size);
// index and ending at count number of elements. The
// elements of the list are compared to the given value using the
// Object.Equals method.
- //
+ //
// This method uses the Array.IndexOf method to perform the
// search.
- //
+ //
public int IndexOf(T item, int index)
{
if (index > _size)
// index and upto count number of elements. The
// elements of the list are compared to the given value using the
// Object.Equals method.
- //
+ //
// This method uses the Array.IndexOf method to perform the
// search.
- //
+ //
public int IndexOf(T item, int index, int count)
{
if (index > _size)
// Inserts an element into this list at a given index. The size of the list
// is increased by one. If required, the capacity of the list is doubled
// before inserting the new element.
- //
+ //
public void Insert(int index, T item)
{
// Note that insertions at the end are legal.
}
// Returns the index of the last occurrence of a given value in a range of
- // this list. The list is searched backwards, starting at the end
- // and ending at the first element in the list. The elements of the list
+ // this list. The list is searched backwards, starting at the end
+ // and ending at the first element in the list. The elements of the list
// are compared to the given value using the Object.Equals method.
- //
+ //
// This method uses the Array.LastIndexOf method to perform the
// search.
- //
+ //
public int LastIndexOf(T item)
{
if (_size == 0)
// Returns the index of the last occurrence of a given value in a range of
// this list. The list is searched backwards, starting at index
- // index and ending at the first element in the list. The
- // elements of the list are compared to the given value using the
+ // index and ending at the first element in the list. The
+ // elements of the list are compared to the given value using the
// Object.Equals method.
- //
+ //
// This method uses the Array.LastIndexOf method to perform the
// search.
- //
+ //
public int LastIndexOf(T item, int index)
{
if (index >= _size)
// index and upto count elements. The elements of
// the list are compared to the given value using the Object.Equals
// method.
- //
+ //
// This method uses the Array.LastIndexOf method to perform the
// search.
- //
+ //
public int LastIndexOf(T item, int index, int count)
{
if ((Count != 0) && (index < 0))
_version++;
}
- // Sorts the elements in this list. Uses the default comparer and
+ // Sorts the elements in this list. Uses the default comparer and
// Array.Sort.
public void Sort()
=> Sort(0, Count, null);
// comparer is null, the elements are compared to each other using
// the IComparable interface, which in that case must be implemented by all
// elements of the list.
- //
+ //
// This method uses the Array.Sort method to sort the elements.
- //
+ //
public void Sort(int index, int count, IComparer<T>? comparer)
{
if (index < 0)
// new elements will be added to the list. To completely clear a list and
// release all memory referenced by the list, execute the following
// statements:
- //
+ //
// list.Clear();
// list.TrimExcess();
- //
+ //
public void TrimExcess()
{
int threshold = (int)(((double)_items.Length) * 0.9);
namespace System.Collections.Generic
{
- // NonRandomizedStringEqualityComparer is the comparer used by default with the Dictionary<string,...>
- // We use NonRandomizedStringEqualityComparer as default comparer as it doesnt use the randomized string hashing which
- // keeps the performance not affected till we hit collision threshold and then we switch to the comparer which is using
+ // NonRandomizedStringEqualityComparer is the comparer used by default with the Dictionary<string,...>
+ // We use NonRandomizedStringEqualityComparer as default comparer as it doesnt use the randomized string hashing which
+ // keeps the performance not affected till we hit collision threshold and then we switch to the comparer which is using
// randomized string hashing.
[Serializable] // Required for compatibility with .NET Core 2.0 as we exposed the NonRandomizedStringEqualityComparer inside the serialization blob
// Needs to be public to support binary serialization compatibility
info.SetType(typeof(GenericEqualityComparer<string>));
}
}
-}
+}
namespace System.Collections
{
internal static partial class HashHelpers
- {
+ {
private static ConditionalWeakTable<object, SerializationInfo>? s_serializationInfoTable;
public static ConditionalWeakTable<object, SerializationInfo> SerializationInfoTable
public const int HashPrime = 101;
- // Table of prime numbers to use as hash table sizes.
+ // Table of prime numbers to use as hash table sizes.
// A typical resize algorithm would pick the smallest prime number in this array
- // that is larger than twice the previous capacity.
- // Suppose our Hashtable currently has capacity x and enough elements are added
- // such that a resize needs to occur. Resizing first computes 2x then finds the
- // first prime in the table greater than 2x, i.e. if primes are ordered
- // p_1, p_2, ..., p_i, ..., it finds p_n such that p_n-1 < 2x < p_n.
- // Doubling is important for preserving the asymptotic complexity of the
- // hashtable operations such as add. Having a prime guarantees that double
- // hashing does not lead to infinite loops. IE, your hash function will be
+ // that is larger than twice the previous capacity.
+ // Suppose our Hashtable currently has capacity x and enough elements are added
+ // such that a resize needs to occur. Resizing first computes 2x then finds the
+ // first prime in the table greater than 2x, i.e. if primes are ordered
+ // p_1, p_2, ..., p_i, ..., it finds p_n such that p_n-1 < 2x < p_n.
+ // Doubling is important for preserving the asymptotic complexity of the
+ // hashtable operations such as add. Having a prime guarantees that double
+ // hashing does not lead to infinite loops. IE, your hash function will be
// h1(key) + i*h2(key), 0 <= i < size. h2 and the size must be relatively prime.
// We prefer the low computation costs of higher prime numbers over the increased
// memory allocation of a fixed prime number i.e. when right sizing a HashSet.
return prime;
}
- //outside of our predefined table.
- //compute the hard way.
+ //outside of our predefined table.
+ //compute the hard way.
for (int i = (min | 1); i < int.MaxValue; i += 2)
{
if (IsPrime(i) && ((i - 1) % HashPrime != 0))
-// Licensed to the .NET Foundation under one or more agreements.
+// 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.
{
// The Hashtable class represents a dictionary of associated keys and values
// with constant lookup time.
- //
+ //
// Objects used as keys in a hashtable must implement the GetHashCode
// and Equals methods (or they can rely on the default implementations
// inherited from Object if key equality is simply reference
// entire time the key is present in the hashtable. In practical terms, this
// means that key objects should be immutable, at least for the time they are
// used as keys in a hashtable.
- //
+ //
// When entries are added to a hashtable, they are placed into
// buckets based on the hashcode of their keys. Subsequent lookups of
// keys will use the hashcode of the keys to only search a particular bucket,
// automatically increased by approximately a factor of two (to be precise, the
// number of hashtable buckets is increased to the smallest prime number that
// is larger than twice the current number of hashtable buckets).
- //
+ //
// Each object provides their own hash function, accessed by calling
- // GetHashCode(). However, one can write their own object
+ // GetHashCode(). However, one can write their own object
// implementing IEqualityComparer and pass it to a constructor on
- // the Hashtable. That hash function (and the equals method on the
+ // the Hashtable. That hash function (and the equals method on the
// IEqualityComparer) would be used for all objects in the table.
//
[DebuggerTypeProxy(typeof(System.Collections.Hashtable.HashtableDebugView))]
public class Hashtable : IDictionary, ISerializable, IDeserializationCallback, ICloneable
{
/*
- This Hashtable uses double hashing. There are hashsize buckets in the
+ This Hashtable uses double hashing. There are hashsize buckets in the
table, and each bucket can contain 0 or 1 element. We use a bit to mark
whether there's been a collision when we inserted multiple elements
- (ie, an inserted item was hashed at least a second time and we probed
+ (ie, an inserted item was hashed at least a second time and we probed
this bucket, but it was already in use). Using the collision bit, we
can terminate lookups & removes for elements that aren't in the hash
table more quickly. We steal the most significant bit from the hash code
to store the collision bit.
Our hash function is of the following form:
-
+
h(key, n) = h1(key) + n*h2(key)
-
+
where n is the number of times we've hit a collided bucket and rehashed
(on this particular lookup). Here are our hash functions:
-
+
h1(key) = GetHash(key); // default implementation calls key.GetHashCode();
h2(key) = 1 + (((h1(key) >> 5) + 1) % (hashsize - 1));
-
+
The h1 can return any number. h2 must return a number between 1 and
- hashsize - 1 that is relatively prime to hashsize (not a problem if
+ hashsize - 1 that is relatively prime to hashsize (not a problem if
hashsize is prime). (Knuth's Art of Computer Programming, Vol. 3, p. 528-9)
If this is true, then we are guaranteed to visit every bucket in exactly
hashsize probes, since the least common multiple of hashsize and h2(key)
will be hashsize * h2(key). (This is the first number where adding h2 to
h1 mod hashsize will be 0 and we will search the same bucket twice).
-
- We previously used a different h2(key, n) that was not constant. That is a
+
+ We previously used a different h2(key, n) that was not constant. That is a
horrifically bad idea, unless you can prove that series will never produce
any identical numbers that overlap when you mod them by hashsize, for all
subranges from i to i+hashsize, for all i. It's not worth investigating,
since there was no clear benefit from using that hash function, and it was
broken.
-
- For efficiency reasons, we've implemented this by storing h1 and h2 in a
+
+ For efficiency reasons, we've implemented this by storing h1 and h2 in a
temporary, and setting a variable called seed equal to h1. We do a probe,
and if we collided, we simply add h2 to seed each time through the loop.
-
+
A good test for h2() is to subclass Hashtable, provide your own implementation
of GetHash() that returns a constant, then add many items to the hash table.
Make sure Count equals the number of items you inserted.
we'd either wipe out the collision bit, or we'd still have an item in
the hash table.
- --
+ --
*/
private const int InitialSize = 3;
// an approximation) is known, specifying it in the constructor can
// eliminate a number of resizing operations that would otherwise be
// performed when elements are added to the hashtable.
- //
+ //
public Hashtable(int capacity) : this(capacity, 1.0f)
{
}
// Smaller load factors cause faster average lookup times at the cost of
// increased memory consumption. A load factor of 1.0 generally provides
// the best balance between speed and size.
- //
+ //
public Hashtable(int capacity, float loadFactor)
{
if (capacity < 0)
if (!(loadFactor >= 0.1f && loadFactor <= 1.0f))
throw new ArgumentOutOfRangeException(nameof(loadFactor), SR.Format(SR.ArgumentOutOfRange_HashtableLoadFactor, .1, 1.0));
- // Based on perf work, .72 is the optimal load factor for this table.
+ // Based on perf work, .72 is the optimal load factor for this table.
_loadFactor = 0.72f * loadFactor;
double rawsize = capacity / _loadFactor;
// Constructs a new hashtable containing a copy of the entries in the given
// dictionary. The hashtable is created with a load factor of 1.0.
- //
+ //
public Hashtable(IDictionary d) : this(d, 1.0f)
{
}
// Constructs a new hashtable containing a copy of the entries in the given
// dictionary. The hashtable is created with the given load factor.
- //
+ //
public Hashtable(IDictionary d, float loadFactor)
: this(d, loadFactor, (IEqualityComparer?)null)
{
HashHelpers.SerializationInfoTable.Add(this, info);
}
- // ?InitHash? is basically an implementation of classic DoubleHashing (see http://en.wikipedia.org/wiki/Double_hashing)
+ // ?InitHash? is basically an implementation of classic DoubleHashing (see http://en.wikipedia.org/wiki/Double_hashing)
//
- // 1) The only ?correctness? requirement is that the ?increment? used to probe
+ // 1) The only ?correctness? requirement is that the ?increment? used to probe
// a. Be non-zero
// b. Be relatively prime to the table size ?hashSize?. (This is needed to insure you probe all entries in the table before you ?wrap? and visit entries already probed)
// 2) Because we choose table sizes to be primes, we just need to insure that the increment is 0 < incr < hashSize
//
// Thus this function would work: Incr = 1 + (seed % (hashSize-1))
- //
- // While this works well for ?uniformly distributed? keys, in practice, non-uniformity is common.
- // In particular in practice we can see ?mostly sequential? where you get long clusters of keys that ?pack?.
- // To avoid bad behavior you want it to be the case that the increment is ?large? even for ?small? values (because small
+ //
+ // While this works well for ?uniformly distributed? keys, in practice, non-uniformity is common.
+ // In particular in practice we can see ?mostly sequential? where you get long clusters of keys that ?pack?.
+ // To avoid bad behavior you want it to be the case that the increment is ?large? even for ?small? values (because small
// values tend to happen more in practice). Thus we multiply ?seed? by a number that will make these small values
// bigger (and not hurt large values). We picked HashPrime (101) because it was prime, and if ?hashSize-1? is not a multiple of HashPrime
// (enforced in GetPrime), then incr has the potential of being every value from 1 to hashSize-1. The choice was largely arbitrary.
- //
+ //
// Computes the hash function: H(key, i) = h1(key) + i*h2(key, hashSize).
- // The out parameter seed is h1(key), while the out parameter
- // incr is h2(key, hashSize). Callers of this function should
+ // The out parameter seed is h1(key), while the out parameter
+ // incr is h2(key, hashSize). Callers of this function should
// add incr each time through a loop.
private uint InitHash(object key, int hashsize, out uint seed, out uint incr)
{
// Adds an entry with the given key and value to this hashtable. An
// ArgumentException is thrown if the key is null or if the key is already
// present in the hashtable.
- //
+ //
public virtual void Add(object key, object? value)
{
Insert(key, value, true);
// Checks if this hashtable contains an entry with the given key. This is
// an O(1) operation.
- //
+ //
public virtual bool ContainsKey(object key)
{
if (key == null)
// using the Object.Equals method. This method performs a linear
// search and is thus be substantially slower than the ContainsKey
// method.
- //
+ //
public virtual bool ContainsValue(object? value)
{
if (value == null)
// Returns the value associated with the given key. If an entry with the
// given key is not found, the returned value is null.
- //
+ //
public virtual object? this[object key]
{
get
// (2) compare the hashcode, if equal, go to step 3. Otherwise end.
// (3) compare the key, if equal, go to step 4. Otherwise end.
// (4) return the value contained in the bucket.
- // After step 3 and before step 4. A writer can kick in a remove the old item and add a new one
+ // After step 3 and before step 4. A writer can kick in a remove the old item and add a new one
// in the same bucket. So in the reader we need to check if the hash table is modified during above steps.
//
- // Writers (Insert, Remove, Clear) will set 'isWriterInProgress' flag before it starts modifying
+ // Writers (Insert, Remove, Clear) will set 'isWriterInProgress' flag before it starts modifying
// the hashtable and will ckear the flag when it is done. When the flag is cleared, the 'version'
- // will be increased. We will repeat the reading if a writer is in progress or done with the modification
+ // will be increased. We will repeat the reading if a writer is in progress or done with the modification
// during the read.
//
- // Our memory model guarantee if we pick up the change in bucket from another processor,
+ // Our memory model guarantee if we pick up the change in bucket from another processor,
// we will see the 'isWriterProgress' flag to be true or 'version' is changed in the reader.
- //
+ //
SpinWait spin = new SpinWait();
while (true)
{
private void UpdateVersion()
{
- // Version might become negative when version is int.MaxValue, but the oddity will be still be correct.
- // So we don't need to special case this.
+ // Version might become negative when version is int.MaxValue, but the oddity will be still be correct.
+ // So we don't need to special case this.
_version++;
}
// reset occupancy
_occupancy = 0;
- // Don't replace any internal state until we've finished adding to the
- // new bucket[]. This serves two purposes:
- // 1) Allow concurrent readers to see valid hashtable contents
+ // Don't replace any internal state until we've finished adding to the
+ // new bucket[]. This serves two purposes:
+ // 1) Allow concurrent readers to see valid hashtable contents
// at all times
- // 2) Protect against an OutOfMemoryException while allocating this
+ // 2) Protect against an OutOfMemoryException while allocating this
// new bucket[].
bucket[] newBuckets = new bucket[newsize];
// Internal method to compare two keys. If you have provided an IComparer
// instance in the constructor, this method will call comparer.Compare(item, key).
// Otherwise, it will call item.Equals(key).
- //
+ //
protected virtual bool KeyEquals(object? item, object key)
{
Debug.Assert(key != null, "key can't be null here!");
// in which the returned collection represents the keys is unspecified, but
// it is guaranteed to be buckets = newBuckets; the same order in which a collection returned by
// GetValues represents the values of the hashtable.
- //
+ //
// The returned collection is live in the sense that any changes
// to the hash table are reflected in this collection. It is not
// a static copy of all the keys in the hash table.
- //
+ //
public virtual ICollection Keys
{
get
// unspecified, but it is guaranteed to be the same order in which a
// collection returned by GetKeys represents the keys of the
// hashtable.
- //
+ //
// The returned collection is live in the sense that any changes
// to the hash table are reflected in this collection. It is not
// a static copy of all the keys in the hash table.
- //
+ //
public virtual ICollection Values
{
get
{
// Set emptySlot number to current bucket if it is the first available bucket that we have seen
// that once contained an entry and also has had a collision.
- // We need to search this entire collision chain because we have to ensure that there are no
+ // We need to search this entire collision chain because we have to ensure that there are no
// duplicate entries in the table.
if (emptySlotNumber == -1 && (_buckets[bucketNumber].key == _buckets) && (_buckets[bucketNumber].hash_coll < 0))//(((buckets[bucketNumber].hash_coll & unchecked(0x80000000))!=0)))
emptySlotNumber = bucketNumber;
// Removes an entry from this hashtable. If an entry with the specified
// key exists in the hashtable, it is removed. An ArgumentException is
// thrown if the key is null.
- //
+ //
public virtual void Remove(object key)
{
if (key == null)
public virtual object SyncRoot => this;
// Returns the number of associations in this hashtable.
- //
+ //
public virtual int Count
{
get { return _count; }
//
// We need to maintain serialization compatibility with Everett and RTM.
// If the comparer is null or a compatible comparer, serialize Hashtable
- // in a format that can be deserialized on Everett and RTM.
+ // in a format that can be deserialized on Everett and RTM.
//
// Also, if the Hashtable is using randomized hashing, serialize the old
// view of the _keycomparer so perevious frameworks don't see the new types
info.AddValue(KeysName, serKeys, typeof(object[]));
info.AddValue(ValuesName, serValues, typeof(object[]));
- // Explicitly check to see if anyone changed the Hashtable while we
+ // Explicitly check to see if anyone changed the Hashtable while we
// were serializing it. That's a race in their code.
if (_version != oldVersion)
{
}
//
- // DeserializationEvent Listener
+ // DeserializationEvent Listener
//
public virtual void OnDeserialization(object? sender)
{
namespace System.Collections
{
- // Base interface for all collections, defining enumerators, size, and
+ // Base interface for all collections, defining enumerators, size, and
// synchronization methods.
public interface ICollection : IEnumerable
{
// Interfaces are not serializable
// CopyTo copies a collection into an Array, starting at a particular
// index into the array.
- //
+ //
void CopyTo(Array array, int index);
// Number of items in the collections.
{ get; }
- // SyncRoot will return an Object to use for synchronization
+ // SyncRoot will return an Object to use for synchronization
// (thread safety). You can use this object in your code to take a
// lock on the collection, even if this collection is a wrapper around
- // another collection. The intent is to tunnel through to a real
+ // another collection. The intent is to tunnel through to a real
// implementation of a collection, and use one of the internal objects
// found in that code.
//
- // In the absence of a static Synchronized method on a collection,
+ // In the absence of a static Synchronized method on a collection,
// the expected usage for SyncRoot would look like this:
- //
+ //
// ICollection col = ...
// lock (col.SyncRoot) {
// // Some operation on the collection, which is now thread safe.
// // This may include multiple operations.
// }
- //
- //
- // The system-provided collections have a static method called
- // Synchronized which will create a thread-safe wrapper around the
- // collection. All access to the collection that you want to be
+ //
+ //
+ // The system-provided collections have a static method called
+ // Synchronized which will create a thread-safe wrapper around the
+ // collection. All access to the collection that you want to be
// thread-safe should go through that wrapper collection. However, if
// you need to do multiple calls on that collection (such as retrieving
// two items, or checking the count then doing something), you should
// NOT use our thread-safe wrapper since it only takes a lock for the
// duration of a single method call. Instead, use Monitor.Enter/Exit
- // or your language's equivalent to the C# lock keyword as mentioned
+ // or your language's equivalent to the C# lock keyword as mentioned
// above.
- //
- // For collections with no publicly available underlying store, the
- // expected implementation is to simply return the this pointer. Note
- // that the this pointer may not be sufficient for collections that
- // wrap other collections; those should return the underlying
+ //
+ // For collections with no publicly available underlying store, the
+ // expected implementation is to simply return the this pointer. Note
+ // that the this pointer may not be sufficient for collections that
+ // wrap other collections; those should return the underlying
// collection's SyncRoot property.
object SyncRoot
{ get; }
- // Is this collection synchronized (i.e., thread-safe)? If you want a
- // thread-safe collection, you can use SyncRoot as an object to
- // synchronize your collection with. If you're using one of the
- // collections in System.Collections, you could call the static
- // Synchronized method to get a thread-safe wrapper around the
+ // Is this collection synchronized (i.e., thread-safe)? If you want a
+ // thread-safe collection, you can use SyncRoot as an object to
+ // synchronize your collection with. If you're using one of the
+ // collections in System.Collections, you could call the static
+ // Synchronized method to get a thread-safe wrapper around the
// underlying collection.
bool IsSynchronized
{ get; }
// The IComparer interface implements a method that compares two objects. It is
// used in conjunction with the Sort and BinarySearch methods on
// the Array and List classes.
- //
+ //
// Interfaces are not serializable
public interface IComparer
{
// Compares two objects. An implementation of this method must return a
// value less than zero if x is less than y, zero if x is equal to y, or a
// value greater than zero if x is greater than y.
- //
+ //
int Compare(object? x, object? y);
}
}
public interface IDictionary : ICollection
{
// Interfaces are not serializable
- // The Item property provides methods to read and edit entries
+ // The Item property provides methods to read and edit entries
// in the Dictionary.
object? this[object key]
{
// Key and Value are undefined before the first call to
// MoveNext and following a call to MoveNext that returned false.
// Enumerators are typically used in while loops of the form
- //
+ //
// IDictionaryEnumerator e = ...;
// while (e.MoveNext()) {
// Object key = e.Key;
// Object value = e.Value;
// ...
// }
- //
+ //
// The IDictionaryEnumerator interface extends the IEnumerator
- // inerface and can thus be used as a regular enumerator. The Current
+ // inerface and can thus be used as a regular enumerator. The Current
// method of an IDictionaryEnumerator returns a DictionaryEntry containing
// the current key and value pair. However, the GetEntry method will
// return the same DictionaryEntry and avoids boxing the DictionaryEntry (boxing
// is somewhat expensive).
- //
+ //
public interface IDictionaryEnumerator : IEnumerator
{
// Returns the key of the current element of the enumeration. The returned
// a call to GetNext that returned false. Multiple calls to
// GetKey with no intervening calls to GetNext will return
// the same object.
- //
+ //
object Key
{
get;
// following a call to GetNext that returned false. Multiple calls
// to GetValue with no intervening calls to GetNext will
// return the same object.
- //
+ //
object? Value
{
get;
// fill up the array, or if there aren't enough elements, it will
// copy as much as possible into the Array. The number of elements
// copied is returned.
- //
+ //
DictionaryEntry Entry
{
get;
// Advances the enumerator to the next element of the enumeration and
// returns a boolean indicating whether an element is available. Upon
// creation, an enumerator is conceptually positioned before the first
- // element of the enumeration, and the first call to MoveNext
+ // element of the enumeration, and the first call to MoveNext
// brings the first element of the enumeration into view.
- //
+ //
bool MoveNext();
// Returns the current element of the enumeration. The returned value is
// undefined before the first call to MoveNext and following a
// call to MoveNext that returned false. Multiple calls to
- // GetCurrent with no intervening calls to MoveNext
+ // GetCurrent with no intervening calls to MoveNext
// will return the same object.
- //
+ //
object? Current
{
get;
set;
}
- // Adds an item to the list. The exact position in the list is
+ // Adds an item to the list. The exact position in the list is
// implementation-dependent, so while ArrayList may always insert
// in the last available location, a SortedList most likely would not.
// The return value is the position the new element was inserted in.
int IndexOf(object? value);
// Inserts value into the list at position index.
- // index must be non-negative and less than or equal to the
+ // index must be non-negative and less than or equal to the
// number of elements in the list. If index equals the number
// of items in the list, then value is appended to the end.
void Insert(int index, object? value);
// See the LICENSE file in the project root for more information.
/*============================================================
**
-**
-**
+**
+**
**
**
** Purpose: List for exceptions.
**
-**
+**
===========================================================*/
namespace System.Collections
}
//
- // We can't cast array of value type to object[], so we don't support
+ // We can't cast array of value type to object[], so we don't support
// widening of primitive types here.
//
object?[]? objects = array as object[];
get
{
// There is no IList<T>.IsFixedSize, so we must assume that only
- // readonly collections are fixed size, if our internal item
+ // readonly collections are fixed size, if our internal item
// collection does not implement IList. Note that Array implements
// IList, and therefore T[] and U[] will be fixed-size.
if (items is IList list)
private static bool IsCompatibleObject(object? value)
{
// Non-null values are fine. Only accept nulls if T is a class or Nullable<U>.
- // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
+ // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
return ((value is T) || (value == null && default(T)! == null));
}
}
}
//
- // We can't cast array of value type to object[], so we don't support
+ // We can't cast array of value type to object[], so we don't support
// widening of primitive types here.
//
object?[]? objects = array as object[];
private static bool IsCompatibleObject(object? value)
{
// Non-null values are fine. Only accept nulls if T is a class or Nullable<U>.
- // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
+ // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
return ((value is T) || (value == null && default(T)! == null));
}
{
return false;
}
-
+
if (Value == null)
{
return other.Value == null;
/// <param name="bytes">The output span which contains the result of the operation, i.e. the decoded binary data.</param>
/// <param name="consumed">The number of input bytes consumed during the operation. This can be used to slice the input for subsequent calls, if necessary.</param>
/// <param name="written">The number of bytes written into the output span. This can be used to slice the output for subsequent calls, if necessary.</param>
- /// </summary>
+ /// </summary>
/// <returns>Returns:
/// - true - The entire input span was successfully parsed.
- /// - false - Only a part of the input span was successfully parsed. Failure causes may include embedded or trailing whitespace,
+ /// - false - Only a part of the input span was successfully parsed. Failure causes may include embedded or trailing whitespace,
/// other illegal Base64 characters, trailing characters after an encoding pad ('='), an input span whose length is not divisible by 4
- /// or a destination span that's too small. <paramref name="consumed"/> and <paramref name="written"/> are set so that
+ /// or a destination span that's too small. <paramref name="consumed"/> and <paramref name="written"/> are set so that
/// parsing can continue with a slower whitespace-tolerant algorithm.
- ///
+ ///
/// Note: This is a cut down version of the implementation of Base64.DecodeFromUtf8(), modified the accept UTF16 chars and act as a fast-path
/// helper for the Convert routines when the input string contains no whitespace.
/// </returns>
private const byte EncodingPad = (byte)'='; // '=', for padding
}
-}
+}
private static int ToBase64_CalculateAndValidateOutputLength(int inputLength, bool insertLineBreaks)
{
- long outlen = ((long)inputLength) / 3 * 4; // the base length - we want integer division here.
+ long outlen = ((long)inputLength) / 3 * 4; // the base length - we want integer division here.
outlen += ((inputLength % 3) != 0) ? 4 : 0; // at most 4 more chars for the remainder
if (outlen == 0)
public static bool TryFromBase64Chars(ReadOnlySpan<char> chars, Span<byte> bytes, out int bytesWritten)
{
// This is actually local to one of the nested blocks but is being declared at the top as we don't want multiple stackallocs
- // for each iteraton of the loop.
+ // for each iteraton of the loop.
Span<char> tempBuffer = stackalloc char[4]; // Note: The tempBuffer size could be made larger than 4 but the size must be a multiple of 4.
bytesWritten = 0;
return false;
}
- // We now loop again to decode the next run of non-space characters.
+ // We now loop again to decode the next run of non-space characters.
}
else
{
return true;
}
- // We now loop again to decode the next run of non-space characters.
+ // We now loop again to decode the next run of non-space characters.
}
}
private static bool IsSpace(this char c) => c == ' ' || c == '\t' || c == '\r' || c == '\n';
/// <summary>
- /// Converts the specified range of a Char array, which encodes binary data as Base64 digits, to the equivalent byte array.
+ /// Converts the specified range of a Char array, which encodes binary data as Base64 digits, to the equivalent byte array.
/// </summary>
/// <param name="inArray">Chars representing Base64 encoding characters</param>
/// <param name="offset">A position within the input array.</param>
}
} // class Convert
} // namespace
-
**
**
**
-** Purpose:
+** Purpose:
** This class represents the current system timezone. It is
-** the only meaningful implementation of the TimeZone class
+** the only meaningful implementation of the TimeZone class
** available in this version.
**
-** The only TimeZone that we support in version 1 is the
+** The only TimeZone that we support in version 1 is the
** CurrentTimeZone as determined by the system timezone.
**
**
return offset.Ticks;
}
- // The start and end times represent the range of universal times that are in DST for that year.
+ // The start and end times represent the range of universal times that are in DST for that year.
// Within that there is an ambiguous hour, usually right at the end, but at the beginning in
// the unusual case of a negative daylight savings delta.
DateTime startTime = daylightTime.Start - offset;
namespace System
{
- // This enum is used to indentify DateTime instances in cases when they are known to be in local time,
+ // This enum is used to indentify DateTime instances in cases when they are known to be in local time,
// UTC time or if this information has not been specified or is not applicable.
public enum DateTimeKind
localTicks = localTicks < DateTime.MinTicks ? DateTime.MinTicks : DateTime.MaxTicks;
}
-
+
return new DateTimeOffset(localTicks, offset);
}
goto NoCarry;
// Carry the subtraction into the higher bits.
- //
+ //
uint* number = (uint*)&bufNum;
uint cur = 3;
do
if ((cmp ^ (int)(d1.uflags & SignMask)) < 0)
return;
- // The divisor is smaller than the dividend and both are non-zero. Calculate the integer remainder using the larger scaling factor.
+ // The divisor is smaller than the dividend and both are non-zero. Calculate the integer remainder using the larger scaling factor.
int scale = (sbyte)(d1.uflags - d2.uflags >> ScaleShift);
if (scale > 0)
{
// Divisor has bits set in the upper 64 bits.
//
- // Divisor must be fully normalized (shifted so bit 31 of the most significant uint is 1).
- // Locate the MSB so we know how much to normalize by.
+ // Divisor must be fully normalized (shifted so bit 31 of the most significant uint is 1).
+ // Locate the MSB so we know how much to normalize by.
// The dividend will be shifted by the same amount so the quotient is not changed.
//
uint tmp = d2.High;
// Sign mask for the flags field. A value of zero in this bit indicates a
// positive Decimal value, and a value of one in this bit indicates a
// negative Decimal value.
- //
+ //
// Look at OleAut's DECIMAL_NEG constant to check for negative values
// in native code.
private const int SignMask = unchecked((int)0x80000000);
// positive and 1 meaning negative.
//
// NOTE: Do not change the order in which these fields are declared. The
- // native methods in this class rely on this particular order.
+ // native methods in this class rely on this particular order.
// Do not rename (binary serialization).
private readonly int flags;
private readonly int hi;
}
// Constructs a Decimal from its constituent parts.
- //
+ //
public Decimal(int lo, int mid, int hi, bool isNegative, byte scale)
{
if (scale > 28)
}
// Compares this object to another object, returning an integer that
- // indicates the relationship.
+ // indicates the relationship.
// Returns a value less than zero if this object
// null is considered to be less than any instance.
// If object is not of type Decimal, this method throws an ArgumentException.
- //
+ //
public int CompareTo(object? value)
{
if (value == null)
throw new OverflowException(SR.Overflow_Int64);
}
- // Converts a Decimal to an ushort. The Decimal
- // value is rounded towards zero to the nearest integer value, and the
+ // Converts a Decimal to an ushort. The Decimal
+ // value is rounded towards zero to the nearest integer value, and the
// result of this operation is returned as an ushort.
//
[CLSCompliant(false)]
return (ushort)temp;
}
- // Converts a Decimal to an unsigned integer. The Decimal
- // value is rounded towards zero to the nearest integer value, and the
+ // Converts a Decimal to an unsigned integer. The Decimal
+ // value is rounded towards zero to the nearest integer value, and the
// result of this operation is returned as an unsigned integer.
//
[CLSCompliant(false)]
throw new OverflowException(SR.Overflow_UInt32);
}
- // Converts a Decimal to an unsigned long. The Decimal
- // value is rounded towards zero to the nearest integer value, and the
+ // Converts a Decimal to an unsigned long. The Decimal
+ // value is rounded towards zero to the nearest integer value, and the
// result of this operation is returned as a long.
//
[CLSCompliant(false)]
// of the target. If the target OR is an interface, the object must implement
// that interface. There are a couple of exceptions
// thrown when a method cannot be returned. If no method matchs the args and
- // ArgumentException is thrown. If multiple methods match the args then
+ // ArgumentException is thrown. If multiple methods match the args then
// an AmbiguousMatchException is thrown.
- //
- // The most specific match will be selected.
- //
+ //
+ // The most specific match will be selected.
+ //
public sealed override MethodBase BindToMethod(
BindingFlags bindingAttr, MethodBase[] match, ref object?[] args,
ParameterModifier[]? modifiers, CultureInfo? cultureInfo, string[]? names, out object? state)
Type[] argTypes = new Type[args.Length];
#region Cache the type of the provided arguments
- // object that contain a null are treated as if they were typeless (but match either object
+ // object that contain a null are treated as if they were typeless (but match either object
// references or value classes). We mark this condition by placing a null in the argTypes array.
for (i = 0; i < args.Length; i++)
{
else if (par.Length > args.Length)
{
#region Shortage of provided parameters
- // If the number of parameters is greater than the number of args then
+ // If the number of parameters is greater than the number of args then
// we are in the situation were we may be using default values.
for (j = args.Length; j < par.Length - 1; j++)
{
}
#endregion
- // If we didn't find a method
+ // If we didn't find a method
if (CurIdx == 0)
throw new MissingMethodException(SR.MissingMember);
objs[i] = parms[i].DefaultValue;
if (paramArrayTypes[0] != null)
- objs[i] = Array.CreateInstance(paramArrayTypes[0], 0); // create an empty array for the
+ objs[i] = Array.CreateInstance(paramArrayTypes[0], 0); // create an empty array for the
else
objs[i] = parms[i].DefaultValue;
MethodBase[] candidates = (MethodBase[])match.Clone();
- // Find all the methods that can be described by the types parameter.
+ // Find all the methods that can be described by the types parameter.
// Remove all of them that cannot.
int CurIdx = 0;
for (i = 0; i < candidates.Length; i++)
// Mark which parameters have not been found in the names list
for (int i = 0; i < pars.Length; i++)
paramOrder[i] = -1;
- // Find the parameters with names.
+ // Find the parameters with names.
for (int i = 0; i < names.Length; i++)
{
int j;
return d;
}
- // V2 api: Creates open or closed delegates to static or instance methods - relaxed signature checking allowed.
+ // V2 api: Creates open or closed delegates to static or instance methods - relaxed signature checking allowed.
public static Delegate CreateDelegate(Type type, object? firstArgument, MethodInfo method) => CreateDelegate(type, firstArgument, method, throwOnBindFailure: true)!;
// V1 api: Creates open delegates to static or instance methods - relaxed signature checking allowed.
**
**
**
-** An attribute to suppress violation messages/warnings
-** by static code analysis tools.
+** An attribute to suppress violation messages/warnings
+** by static code analysis tools.
+**
**
-**
===========================================================*/
namespace System.Diagnostics.CodeAnalysis
/*============================================================
**
-**
+**
**
** Purpose: The contract class allows for expressing preconditions,
** postconditions, and object invariants about methods in source
/// method for a class. The method can have any name, but it must
/// return "void" and take no parameters. The body of the method
/// must consist solely of one or more calls to the method
- /// Contract.Invariant. A suggested name for the method is
+ /// Contract.Invariant. A suggested name for the method is
/// "ObjectInvariant".
/// </summary>
[Conditional("CONTRACTS_FULL")]
/// WARNING: A binary rewriter must be used to insert runtime enforcement of these contracts.
/// Otherwise some contracts like Ensures can only be checked statically and will not throw exceptions during runtime when contracts are violated.
/// Please note this class uses conditional compilation to help avoid easy mistakes. Defining the preprocessor
- /// symbol CONTRACTS_PRECONDITIONS will include all preconditions expressed using Contract.Requires in your
+ /// symbol CONTRACTS_PRECONDITIONS will include all preconditions expressed using Contract.Requires in your
/// build. The symbol CONTRACTS_FULL will include postconditions and object invariants, and requires the binary rewriter.
/// </remarks>
public static partial class Contract
#region ForAll
/// <summary>
- /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
+ /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
/// for all integers starting from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.
/// </summary>
/// <param name="fromInclusive">First integer to pass to <paramref name="predicate"/>.</param>
/// <param name="toExclusive">One greater than the last integer to pass to <paramref name="predicate"/>.</param>
/// <param name="predicate">Function that is evaluated from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.</param>
- /// <returns><c>true</c> if <paramref name="predicate"/> returns <c>true</c> for all integers
+ /// <returns><c>true</c> if <paramref name="predicate"/> returns <c>true</c> for all integers
/// starting from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.</returns>
/// <seealso cref="System.Collections.Generic.List<T>.TrueForAll"/>
[Pure]
/// <summary>
- /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
+ /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
/// for all elements in the <paramref name="collection"/>.
/// </summary>
/// <param name="collection">The collection from which elements will be drawn from to pass to <paramref name="predicate"/>.</param>
#region Exists
/// <summary>
- /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
+ /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
/// for any integer starting from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.
/// </summary>
/// <param name="fromInclusive">First integer to pass to <paramref name="predicate"/>.</param>
}
/// <summary>
- /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
+ /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
/// for any element in the <paramref name="collection"/>.
/// </summary>
/// <param name="collection">The collection from which elements will be drawn from to pass to <paramref name="predicate"/>.</param>
/// <summary>
/// Without contract rewriting, failing Assert/Assumes end up calling this method.
/// Code going through the contract rewriter never calls this method. Instead, the rewriter produced failures call
- /// System.Runtime.CompilerServices.ContractHelper.RaiseContractFailedEvent, followed by
+ /// System.Runtime.CompilerServices.ContractHelper.RaiseContractFailedEvent, followed by
/// System.Runtime.CompilerServices.ContractHelper.TriggerFailure.
/// </summary>
[System.Diagnostics.DebuggerNonUserCode]
/// <summary>
/// Allows a managed application environment such as an interactive interpreter (IronPython)
- /// to be notified of contract failures and
+ /// to be notified of contract failures and
/// potentially "handle" them, either by throwing a particular exception type, etc. If any of the
/// event handlers sets the Cancel flag in the ContractFailedEventArgs, then the Contract class will
- /// not pop up an assert dialog box or trigger escalation policy. Hooking this event requires
+ /// not pop up an assert dialog box or trigger escalation policy. Hooking this event requires
/// full trust, because it will inform you of bugs in the appdomain and because the event handler
/// could allow you to continue execution.
/// </summary>
Assume,
}
} // namespace System.Runtime.CompilerServices
-
{
if (s_FailCore != null)
{
- s_FailCore(stackTrace, message, detailMessage, errorSource);
+ s_FailCore(stackTrace, message, detailMessage, errorSource);
return;
}
{
if (s_WriteCore != null)
{
- s_WriteCore(message);
+ s_WriteCore(message);
return;
}
// We don't want to write UTF-16 to a file like standard error. Ideally we would transcode this
// to UTF8, but the downside of that is it pulls in a bunch of stuff into what is ideally
// a path with minimal dependencies (as to prevent re-entrency), so we'll take the strategy
- // of just throwing away any non ASCII characters from the message and writing the rest
+ // of just throwing away any non ASCII characters from the message and writing the rest
const int BufferLength = 256;
{
if (s_FailCore != null)
{
- s_FailCore(stackTrace, message, detailMessage, errorSource);
+ s_FailCore(stackTrace, message, detailMessage, errorSource);
return;
}
{
if (s_WriteCore != null)
{
- s_WriteCore(message);
+ s_WriteCore(message);
return;
}
- // really huge messages mess up both VS and dbmon, so we chop it up into
- // reasonable chunks if it's too big. This is the number of characters
+ // really huge messages mess up both VS and dbmon, so we chop it up into
+ // reasonable chunks if it's too big. This is the number of characters
// that OutputDebugstring chunks at.
const int WriteChunkLength = 4091;
}
}
}
-
+
public virtual void WriteLine(string? message)
{
Write(message + Environment.NewLine);
namespace System.Diagnostics
{
- // Attribute class used by the compiler to mark modules.
+ // Attribute class used by the compiler to mark modules.
// If present, then debugging information for everything in the
// assembly was generated by the compiler, and will be preserved
// by the Runtime so that the debugger can provide full functionality
// Never element should never show
// Expanded expansion of the class is done, so that all visible internal members are shown
// Collapsed expansion of the class is not performed. Internal visible members are hidden
- // RootHidden The target element itself should not be shown, but should instead be
+ // RootHidden The target element itself should not be shown, but should instead be
// automatically expanded to have its members displayed.
// Default value is collapsed
{
Never = 0,
//Expanded is not supported in this release
- //Expanded = 1,
+ //Expanded = 1,
Collapsed = 2,
RootHidden = 3
}
- // the one currently supported with the csee.dat
- // (mcee.dat, autoexp.dat) file.
+ // the one currently supported with the csee.dat
+ // (mcee.dat, autoexp.dat) file.
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
public sealed class DebuggerBrowsableAttribute : Attribute
{
namespace System.Diagnostics
{
- // This attribute is used to control what is displayed for the given class or field
+ // This attribute is used to control what is displayed for the given class or field
// in the data windows in the debugger. The single argument to this attribute is
- // the string that will be displayed in the value column for instances of the type.
- // This string can include text between { and } which can be either a field,
- // property or method (as will be documented in mscorlib). In the C# case,
- // a general expression will be allowed which only has implicit access to the this pointer
- // for the current instance of the target type. The expression will be limited,
- // however: there is no access to aliases, locals, or pointers.
+ // the string that will be displayed in the value column for instances of the type.
+ // This string can include text between { and } which can be either a field,
+ // property or method (as will be documented in mscorlib). In the C# case,
+ // a general expression will be allowed which only has implicit access to the this pointer
+ // for the current instance of the target type. The expression will be limited,
+ // however: there is no access to aliases, locals, or pointers.
// In addition, attributes on properties referenced in the expression are not processed.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Assembly, AllowMultiple = true)]
public sealed class DebuggerDisplayAttribute : Attribute
TargetTypeName = value.AssemblyQualifiedName;
_target = value;
- }
+ }
}
public string? TargetTypeName { get; set; }
public string VisualizerTypeName { get; }
public string? Description { get; set; }
-
+
public Type? Target
{
get => _target;
private int _numOfFrames;
private int _methodsToSkip;
-
+
/// <summary>
/// Stack frames comprising this stack trace.
/// </summary>
}
/// <summary>
- /// TraceFormat is used to specify options for how the
+ /// TraceFormat is used to specify options for how the
/// string-representation of a StackTrace should be generated.
/// </summary>
internal enum TraceFormat
#if !CORERT
/// <summary>
- /// Builds a readable representation of the stack trace, specifying
+ /// Builds a readable representation of the stack trace, specifying
/// the format for backwards compatibility.
/// </summary>
internal string ToString(TraceFormat traceFormat)
{
StackFrame? sf = GetFrame(iFrameIndex);
MethodBase? mb = sf?.GetMethod();
- if (mb != null && (ShowInStackTrace(mb) ||
+ if (mb != null && (ShowInStackTrace(mb) ||
(iFrameIndex == _numOfFrames - 1))) // Don't filter last frame
{
// We want a newline at the end of every line except for the last
if ((mb.MethodImplementationFlags & MethodImplAttributes.AggressiveInlining) != 0)
{
// Aggressive Inlines won't normally show in the StackTrace; however for Tier0 Jit and
- // cross-assembly AoT/R2R these inlines will be blocked until Tier1 Jit re-Jits
+ // cross-assembly AoT/R2R these inlines will be blocked until Tier1 Jit re-Jits
// them when they will inline. We don't show them in the StackTrace to bring consistency
// between this first-pass asm and fully optimized asm.
return false;
Type? declaringType = mb.DeclaringType;
// Methods don't always have containing types, for example dynamic RefEmit generated methods.
- if (declaringType != null &&
+ if (declaringType != null &&
declaringType.IsDefined(typeof(StackTraceHiddenAttribute), inherit: false))
{
// Don't show where StackTraceHidden is applied to the containing Type of the method.
{
/// <summary>
/// Tracks activities. This is meant to be a singleton (accessed by the ActivityTracer.Instance static property)
- ///
+ ///
/// Logically this is simply holds the m_current variable that holds the async local that holds the current ActivityInfo
- /// An ActivityInfo is represents a activity (which knows its creator and thus knows its path).
+ /// An ActivityInfo is represents a activity (which knows its creator and thus knows its path).
///
/// Most of the magic is in the async local (it gets copied to new tasks)
- ///
- /// On every start event call OnStart
- ///
+ ///
+ /// On every start event call OnStart
+ ///
/// Guid activityID;
/// Guid relatedActivityID;
/// if (OnStart(activityName, out activityID, out relatedActivityID, ForceStop, options))
/// // Log Start event with activityID and relatedActivityID
- ///
+ ///
/// On every stop event call OnStop
- ///
+ ///
/// Guid activityID;
/// if (OnStop(activityName, ref activityID ForceStop))
/// // Stop event with activityID
- ///
+ ///
/// On any normal event log the event with activityTracker.CurrentActivityId
/// </summary>
internal class ActivityTracker
/// <summary>
/// Called on work item begins. The activity name = providerName + activityName without 'Start' suffix.
- /// It updates CurrentActivityId to track.
- ///
- /// It returns true if the Start should be logged, otherwise (if it is illegal recursion) it return false.
- ///
+ /// It updates CurrentActivityId to track.
+ ///
+ /// It returns true if the Start should be logged, otherwise (if it is illegal recursion) it return false.
+ ///
/// The start event should use as its activity ID the CurrentActivityId AFTER calling this routine and its
- /// RelatedActivityID the CurrentActivityId BEFORE calling this routine (the creator).
- ///
+ /// RelatedActivityID the CurrentActivityId BEFORE calling this routine (the creator).
+ ///
/// If activity tracing is not on, then activityId and relatedActivityId are not set
/// </summary>
public void OnStart(string providerName, string activityName, int task, ref Guid activityId, ref Guid relatedActivityId, EventActivityOptions options)
{
// We used to rely on the TPL provider turning us on, but that has the disadvantage that you don't get Start-Stop tracking
// until you use Tasks for the first time (which you may never do). Thus we change it to pull rather tan push for whether
- // we are enabled.
+ // we are enabled.
if (m_checkedForEnable)
return;
m_checkedForEnable = true;
if (currentActivity != null)
{
- // Stop activity tracking if we reached the maximum allowed depth
+ // Stop activity tracking if we reached the maximum allowed depth
if (currentActivity.m_level >= MAX_ACTIVITY_DEPTH)
{
activityId = Guid.Empty;
// The previous ID is my 'causer' and becomes my related activity ID
relatedActivityId = EventSource.CurrentThreadActivityId;
- // Add to the list of started but not stopped activities.
+ // Add to the list of started but not stopped activities.
ActivityInfo newActivity = new ActivityInfo(fullActivityName, id, currentActivity, relatedActivityId, options);
m_current.Value = newActivity;
- // Remember the current ID so we can log it
+ // Remember the current ID so we can log it
activityId = newActivity.ActivityId;
-
+
if (log.Debug)
{
log.DebugFacilityMessage("OnStartRetActivityState", ActivityInfo.LiveActivities(newActivity));
return;
var fullActivityName = NormalizeActivityName(providerName, activityName, task);
-
+
var log = TplEventSource.Log;
if (log.Debug)
{
for (; ; ) // This is a retry loop.
{
ActivityInfo? currentActivity = m_current.Value;
- ActivityInfo? newCurrentActivity = null; // if we have seen any live activities (orphans), at he first one we have seen.
+ ActivityInfo? newCurrentActivity = null; // if we have seen any live activities (orphans), at he first one we have seen.
// Search to find the activity to stop in one pass. This insures that we don't let one mistake
- // (stopping something that was not started) cause all active starts to be stopped
- // By first finding the target start to stop we are more robust.
+ // (stopping something that was not started) cause all active starts to be stopped
+ // By first finding the target start to stop we are more robust.
ActivityInfo? activityToStop = FindActiveActivity(fullActivityName, currentActivity);
// ignore stops where we can't find a start because we may have popped them previously.
activityId = activityToStop.ActivityId;
- // See if there are any orphans that need to be stopped.
+ // See if there are any orphans that need to be stopped.
ActivityInfo? orphan = currentActivity;
while (orphan != activityToStop && orphan != null)
{
}
if (orphan.CanBeOrphan())
{
- // We can't pop anything after we see a valid orphan, remember this for later when we update m_current.
+ // We can't pop anything after we see a valid orphan, remember this for later when we update m_current.
if (newCurrentActivity == null)
newCurrentActivity = orphan;
}
// try to Stop the activity atomically. Other threads may be trying to do this as well.
if (Interlocked.CompareExchange(ref activityToStop.m_stopped, 1, 0) == 0)
{
- // I succeeded stopping this activity. Now we update our m_current pointer
+ // I succeeded stopping this activity. Now we update our m_current pointer
// If I haven't yet determined the new current activity, it is my creator.
if (newCurrentActivity == null)
}
return;
}
- // We failed to stop it. We must have hit a race to stop it. Just start over and try again.
+ // We failed to stop it. We must have hit a race to stop it. Just start over and try again.
}
}
{
if (m_current == null)
{
- // Catch the not Implemented
+ // Catch the not Implemented
try
{
m_current = new AsyncLocal<ActivityInfo?>(ActivityChanging);
// send message to debugger without delay
System.Diagnostics.Debugger.Log(0, null, "Activity Enabled() called but AsyncLocals Not Supported (pre V4.6). Ignoring Enable");
#endif
- }
+ }
}
}
#region private
/// <summary>
- /// Searched for a active (nonstopped) activity with the given name. Returns null if not found.
+ /// Searched for a active (nonstopped) activity with the given name. Returns null if not found.
/// </summary>
private ActivityInfo? FindActiveActivity(string name, ActivityInfo? startLocation)
{
/// An ActivityInfo represents a particular activity. It is almost read-only. The only
/// fields that change after creation are
/// m_lastChildID - used to generate unique IDs for the children activities and for the most part can be ignored.
- /// m_stopped - indicates that this activity is dead
- /// This read-only-ness is important because an activity's m_creator chain forms the
+ /// m_stopped - indicates that this activity is dead
+ /// This read-only-ness is important because an activity's m_creator chain forms the
/// 'Path of creation' for the activity (which is also its unique ID) but is also used as
/// the 'list of live parents' which indicate of those ancestors, which are alive (if they
- /// are not marked dead they are alive).
+ /// are not marked dead they are alive).
/// </summary>
private class ActivityInfo
{
#region CreateActivityPathGuid
/// <summary>
- /// Logically every activity Path (see Path()) that describes the activities that caused this
- /// (rooted in an activity that predates activity tracking.
+ /// Logically every activity Path (see Path()) that describes the activities that caused this
+ /// (rooted in an activity that predates activity tracking.
///
/// We wish to encode this path in the Guid to the extent that we can. Many of the paths have
/// many small numbers in them and we take advantage of this in the encoding to output as long
- /// a path in the GUID as possible.
- ///
+ /// a path in the GUID as possible.
+ ///
/// Because of the possibility of GUID collision, we only use 96 of the 128 bits of the GUID
- /// for encoding the path. The last 32 bits are a simple checksum (and random number) that
- /// identifies this as using the convention defined here.
+ /// for encoding the path. The last 32 bits are a simple checksum (and random number) that
+ /// identifies this as using the convention defined here.
///
/// It returns both the GUID which has the path as well as the offset that points just beyond
/// the end of the activity (so it can be appended to). Note that if the end is in a nibble
/// (it uses nibbles instead of bytes as the unit of encoding, then it will point at the unfinished
- /// byte (since the top nibble can't be zero you can determine if this is true by seeing if
- /// this byte is nonZero. This offset is needed to efficiently create the ID for child activities.
+ /// byte (since the top nibble can't be zero you can determine if this is true by seeing if
+ /// this byte is nonZero. This offset is needed to efficiently create the ID for child activities.
/// </summary>
private unsafe void CreateActivityPathGuid(out Guid idRet, out int activityPathGuidOffset)
{
/// <summary>
/// If we can't fit the activity Path into the GUID we come here. What we do is simply
- /// generate a 4 byte number (s_nextOverflowId). Then look for an ancestor that has
+ /// generate a 4 byte number (s_nextOverflowId). Then look for an ancestor that has
/// sufficient space for this ID. By doing this, we preserve the fact that this activity
/// is a child (of unknown depth) from that ancestor.
/// </summary>
private unsafe void CreateOverflowGuid(Guid* outPtr)
{
- // Search backwards for an ancestor that has sufficient space to put the ID.
+ // Search backwards for an ancestor that has sufficient space to put the ID.
for (ActivityInfo? ancestor = m_creator; ancestor != null; ancestor = ancestor.m_creator)
{
- if (ancestor.m_activityPathGuidOffset <= 10) // we need at least 2 bytes.
+ if (ancestor.m_activityPathGuidOffset <= 10) // we need at least 2 bytes.
{
- uint id = unchecked((uint)Interlocked.Increment(ref ancestor.m_lastChildID)); // Get a unique ID
+ uint id = unchecked((uint)Interlocked.Increment(ref ancestor.m_lastChildID)); // Get a unique ID
// Try to put the ID into the GUID
*outPtr = ancestor.m_guid;
int endId = AddIdToGuid(outPtr, ancestor.m_activityPathGuidOffset, id, true);
/// we operate on nibbles (which are nice because they show up as hex digits). The
/// list is ended with a end nibble (0) and depending on the nibble value (Below)
/// the value is either encoded into nibble itself or it can spill over into the
- /// bytes that follow.
+ /// bytes that follow.
/// </summary>
enum NumberListCodes : byte
{
- End = 0x0, // ends the list. No valid value has this prefix.
+ End = 0x0, // ends the list. No valid value has this prefix.
LastImmediateValue = 0xA,
PrefixCode = 0xB, // all the 'long' encodings go here. If the next nibble is MultiByte1-4
- // than this is a 'overflow' id. Unlike the hierarchical IDs these are
- // allocated densely but don't tell you anything about nesting. we use
+ // than this is a 'overflow' id. Unlike the hierarchical IDs these are
+ // allocated densely but don't tell you anything about nesting. we use
// these when we run out of space in the GUID to store the path.
- MultiByte1 = 0xC, // 1 byte follows. If this Nibble is in the high bits, it the high bits of the number are stored in the low nibble.
- // commented out because the code does not explicitly reference the names (but they are logically defined).
+ MultiByte1 = 0xC, // 1 byte follows. If this Nibble is in the high bits, it the high bits of the number are stored in the low nibble.
+ // commented out because the code does not explicitly reference the names (but they are logically defined).
// MultiByte2 = 0xD, // 2 bytes follow (we don't bother with the nibble optimization)
// MultiByte3 = 0xE, // 3 bytes follow (we don't bother with the nibble optimization)
// MultiByte4 = 0xF, // 4 bytes follow (we don't bother with the nibble optimization)
/// Add the activity id 'id' to the output Guid 'outPtr' starting at the offset 'whereToAddId'
/// Thus if this number is 6 that is where 'id' will be added. This will return 13 (12
- /// is the maximum number of bytes that fit in a GUID) if the path did not fit.
+ /// is the maximum number of bytes that fit in a GUID) if the path did not fit.
/// If 'overflow' is true, then the number is encoded as an 'overflow number (which has a
- /// special (longer prefix) that indicates that this ID is allocated differently
+ /// special (longer prefix) that indicates that this ID is allocated differently
private static unsafe int AddIdToGuid(Guid* outPtr, int whereToAddId, uint id, bool overflow = false)
{
byte* ptr = (byte*)outPtr;
if (endPtr <= ptr + 2) // I need at least 2 bytes
return 13;
- // Write out the prefix code nibble and the length nibble
+ // Write out the prefix code nibble and the length nibble
WriteNibble(ref ptr, endPtr, (uint)NumberListCodes.PrefixCode);
}
// The rest is the same for overflow and non-overflow case
WriteNibble(ref ptr, endPtr, (uint)NumberListCodes.MultiByte1 + (len - 1));
- // Do we have an odd nibble? If so flush it or use it for the 12 byte case.
+ // Do we have an odd nibble? If so flush it or use it for the 12 byte case.
if (ptr < endPtr && *ptr != 0)
{
- // If the value < 4096 we can use the nibble we are otherwise just outputting as padding.
+ // If the value < 4096 we can use the nibble we are otherwise just outputting as padding.
if (id < 4096)
{
- // Indicate this is a 1 byte multicode with 4 high order bits in the lower nibble.
+ // Indicate this is a 1 byte multicode with 4 high order bits in the lower nibble.
*ptr = (byte)(((uint)NumberListCodes.MultiByte1 << 4) + (id >> 8));
- id &= 0xFF; // Now we only want the low order bits.
+ id &= 0xFF; // Now we only want the low order bits.
}
ptr++;
}
}
}
- // Compute the checksum
+ // Compute the checksum
uint* sumPtr = (uint*)outPtr;
- // We set the last DWORD the sum of the first 3 DWORDS in the GUID. This
- // This last number is a random number (it identifies us as us) the process ID to make it unique per process.
+ // We set the last DWORD the sum of the first 3 DWORDS in the GUID. This
+ // This last number is a random number (it identifies us as us) the process ID to make it unique per process.
sumPtr[3] = (sumPtr[0] + sumPtr[1] + sumPtr[2] + 0x599D99AD) ^ EventSource.s_currentPid;
return (int)(ptr - ((byte*)outPtr));
}
/// <summary>
- /// Write a single Nible 'value' (must be 0-15) to the byte buffer represented by *ptr.
+ /// Write a single Nible 'value' (must be 0-15) to the byte buffer represented by *ptr.
/// Will not go past 'endPtr'. Also it assumes that we never write 0 so we can detect
- /// whether a nibble has already been written to ptr because it will be nonzero.
+ /// whether a nibble has already been written to ptr because it will be nonzero.
/// Thus if it is non-zero it adds to the current byte, otherwise it advances and writes
- /// the new byte (in the high bits) of the next byte.
+ /// the new byte (in the high bits) of the next byte.
/// </summary>
private static unsafe void WriteNibble(ref byte* ptr, byte* endPtr, uint value)
{
internal readonly Guid m_guid; // Activity Guid, it is basically an encoding of the Path() (see CreateActivityPathGuid)
internal readonly int m_activityPathGuidOffset; // Keeps track of where in m_guid the causality path stops (used to generated child GUIDs)
internal readonly int m_level; // current depth of the Path() of the activity (used to keep recursion under control)
- internal readonly EventActivityOptions m_eventOptions; // Options passed to start.
+ internal readonly EventActivityOptions m_eventOptions; // Options passed to start.
internal long m_lastChildID; // used to create a unique ID for my children activities
internal int m_stopped; // This work item has stopped
internal readonly ActivityInfo? m_creator; // My parent (creator). Forms the Path() for the activity.
#endregion
}
- // This callback is used to initialize the m_current AsyncLocal Variable.
+ // This callback is used to initialize the m_current AsyncLocal Variable.
// Its job is to keep the ETW Activity ID (part of thread local storage) in sync
// with m_current.ActivityID
void ActivityChanging(AsyncLocalValueChangedArgs<ActivityInfo?> args)
ActivityInfo? cur = args.CurrentValue;
ActivityInfo? prev = args.PreviousValue;
- // Are we popping off a value? (we have a prev, and it creator is cur)
+ // Are we popping off a value? (we have a prev, and it creator is cur)
// Then check if we should use the GUID at the time of the start event
if (prev != null && prev.m_creator == cur)
{
}
}
- // OK we did not have an explicit SetActivityID set. Then we should be
- // setting the activity to current ActivityInfo. However that activity
- // might be dead, in which case we should skip it, so we never set
- // the ID to dead things.
+ // OK we did not have an explicit SetActivityID set. Then we should be
+ // setting the activity to current ActivityInfo. However that activity
+ // might be dead, in which case we should skip it, so we never set
+ // the ID to dead things.
while (cur != null)
{
- // We found a live activity (typically the first time), set it to that.
+ // We found a live activity (typically the first time), set it to that.
if (cur.m_stopped == 0)
{
EventSource.SetCurrentThreadActivityId(cur.ActivityId);
cur = cur.m_creator;
}
// we can get here if there is no information on our activity stack (everything is dead)
- // currently we do nothing, as that seems better than setting to Guid.Emtpy.
+ // currently we do nothing, as that seems better than setting to Guid.Emtpy.
}
/// <summary>
/// Async local variables have the property that the are automatically copied whenever a task is created and used
/// while that task is running. Thus m_current 'flows' to any task that is caused by the current thread that
- /// last set it.
- ///
- /// This variable points to a linked list that represents all Activities that have started but have not stopped.
+ /// last set it.
+ ///
+ /// This variable points to a linked list that represents all Activities that have started but have not stopped.
/// </summary>
AsyncLocal<ActivityInfo?>? m_current;
bool m_checkedForEnable;
// Used to create unique IDs at the top level. Not used for nested Ids (each activity has its own id generator)
static long m_nextId = 0;
- private const ushort MAX_ACTIVITY_DEPTH = 100; // Limit maximum depth of activities to be tracked at 100.
+ private const ushort MAX_ACTIVITY_DEPTH = 100; // Limit maximum depth of activities to be tracked at 100.
// This will avoid leaking memory in case of activities that are never stopped.
#endregion
/******************************** SUPPORT *****************************/
/// <summary>
/// This is supplied by the framework. It is has the semantics that the value is copied to any new Tasks that is created
- /// by the current task. Thus all causally related code gets this value. Note that reads and writes to this VARIABLE
+ /// by the current task. Thus all causally related code gets this value. Note that reads and writes to this VARIABLE
/// (not what it points it) to this does not need to be protected by locks because it is inherently thread local (you always
- /// only get your thread local copy which means that you never have races.
+ /// only get your thread local copy which means that you never have races.
/// </summary>
- ///
+ ///
[EventSource(Name = "Microsoft.Tasks.Nuget")]
internal class TplEventSource : EventSource
{
#endif
#if ES_BUILD_AGAINST_DOTNET_V35 || ES_BUILD_PCL || NO_ASYNC_LOCAL
- // In these cases we don't have any Async local support. Do nothing.
+ // In these cases we don't have any Async local support. Do nothing.
internal sealed class AsyncLocalValueChangedArgs<T>
{
public T PreviousValue { get { return default(T); } }
internal sealed class AsyncLocal<T>
{
- public AsyncLocal(Action<AsyncLocalValueChangedArgs<T>> valueChangedHandler) {
+ public AsyncLocal(Action<AsyncLocalValueChangedArgs<T>> valueChangedHandler) {
throw new NotImplementedException("AsyncLocal only available on V4.6 and above");
}
public T Value
#region Global CounterGroup Array management
- // We need eventCounters to 'attach' themselves to a particular EventSource.
- // this table provides the mapping from EventSource -> CounterGroup
- // which represents this 'attached' information.
+ // We need eventCounters to 'attach' themselves to a particular EventSource.
+ // this table provides the mapping from EventSource -> CounterGroup
+ // which represents this 'attached' information.
private static WeakReference<CounterGroup>[]? s_counterGroups;
private static void EnsureEventSourceIndexAvailable(int eventSourceIndex)
}
_nextPollingTimeStamp = DateTime.UtcNow + new TimeSpan(0, 0, (int)pollingIntervalInSeconds);
-
+
// Create the polling thread and init all the shared state if needed
if (s_pollingThread == null)
{
#endif
{
/// <summary>
- /// DiagnosticCounter is an abstract class that serves as the parent class for various Counter* classes,
+ /// DiagnosticCounter is an abstract class that serves as the parent class for various Counter* classes,
/// namely EventCounter, PollingCounter, IncrementingEventCounter, and IncrementingPollingCounter.
/// </summary>
public abstract class DiagnosticCounter : IDisposable
{
/// <summary>
/// All Counters live as long as the EventSource that they are attached to unless they are
- /// explicitly Disposed.
+ /// explicitly Disposed.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="eventSource">The event source.</param>
/// Removes the counter from set that the EventSource will report on. After being disposed, this
/// counter will do nothing and its resource will be reclaimed if all references to it are removed.
/// If an EventCounter is not explicitly disposed it will be cleaned up automatically when the
- /// EventSource it is attached to dies.
+ /// EventSource it is attached to dies.
/// </summary>
public void Dispose()
{
{
/// <summary>
/// Provides the ability to collect statistics through EventSource
- ///
+ ///
/// See https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.Tracing/documentation/EventCounterTutorial.md
- /// for a tutorial guide.
- ///
+ /// for a tutorial guide.
+ ///
/// See https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestEventCounter.cs
- /// which shows tests, which are also useful in seeing actual use.
+ /// which shows tests, which are also useful in seeing actual use.
/// </summary>
public partial class EventCounter : DiagnosticCounter
{
/// <summary>
/// Initializes a new instance of the <see cref="EventCounter"/> class.
/// EVentCounters live as long as the EventSource that they are attached to unless they are
- /// explicitly Disposed.
+ /// explicitly Disposed.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="eventSource">The event source.</param>
}
/// <summary>
- /// Writes 'value' to the stream of values tracked by the counter. This updates the sum and other statistics that will
- /// be logged on the next timer interval.
+ /// Writes 'value' to the stream of values tracked by the counter. This updates the sum and other statistics that will
+ /// be logged on the next timer interval.
/// </summary>
/// <param name="value">The value.</param>
public void WriteMetric(float value)
if (result == UnusedBufferSlotValue)
{
- // CompareExchange succeeded
+ // CompareExchange succeeded
_bufferedValuesIndex = i;
return;
}
#endif
/*
- EventDescriptor was public in the separate System.Diagnostics.Tracing assembly(pre NS2.0),
+ EventDescriptor was public in the separate System.Diagnostics.Tracing assembly(pre NS2.0),
now the move to CoreLib marked them as private.
- While they are technically private (it's a contract used between the library and the ILC toolchain),
+ While they are technically private (it's a contract used between the library and the ILC toolchain),
we need them to be rooted and exported from shared library for the system to work.
- For now I'm simply marking them as public again.A cleaner solution might be to use.rd.xml to
+ For now I'm simply marking them as public again.A cleaner solution might be to use.rd.xml to
root them and modify shared library definition to force export them.
*/
#if ES_BUILD_PN
};
/// <summary>
- /// Only here because System.Diagnostics.EventProvider needs one more extensibility hook (when it gets a
+ /// Only here because System.Diagnostics.EventProvider needs one more extensibility hook (when it gets a
/// controller callback)
/// </summary>
#if ES_BUILD_STANDALONE
{
// This is the windows EVENT_DATA_DESCRIPTOR structure. We expose it because this is what
// subclasses of EventProvider use when creating efficient (but unsafe) version of
- // EventWrite. We do make it a nested type because we really don't expect anyone to use
- // it except subclasses (and then only rarely).
+ // EventWrite. We do make it a nested type because we really don't expect anyone to use
+ // it except subclasses (and then only rarely).
[StructLayout(LayoutKind.Sequential)]
public struct EventData
{
/// <summary>
/// A struct characterizing ETW sessions (identified by the etwSessionId) as
/// activity-tracing-aware or legacy. A session that's activity-tracing-aware
- /// has specified one non-zero bit in the reserved range 44-47 in the
+ /// has specified one non-zero bit in the reserved range 44-47 in the
/// 'allKeywords' value it passed in for a specific EventProvider.
/// </summary>
public struct SessionInfo
internal bool m_disposed; // when true provider has unregistered
[ThreadStatic]
- private static WriteEventErrorCode s_returnCode; // The last return code
+ private static WriteEventErrorCode s_returnCode; // The last return code
private const int s_basicTypeAllocationBufferSize = 16;
private const int s_etwMaxNumberArguments = 128;
};
// Because callbacks happen on registration, and we need the callbacks for those setup
- // we can't call Register in the constructor.
+ // we can't call Register in the constructor.
//
// Note that EventProvider should ONLY be used by EventSource. In particular because
// it registers a callback from native code you MUST dispose it BEFORE shutdown, otherwise
- // you may get native callbacks during shutdown when we have destroyed the delegate.
- // EventSource has special logic to do this, no one else should be calling EventProvider.
+ // you may get native callbacks during shutdown when we have destroyed the delegate.
+ // EventSource has special logic to do this, no one else should be calling EventProvider.
internal EventProvider(EventProviderType providerType)
{
switch (providerType)
/// <summary>
/// This method registers the controlGuid of this class with ETW. We need to be running on
- /// Vista or above. If not a PlatformNotSupported exception will be thrown. If for some
- /// reason the ETW Register call failed a NotSupported exception will be thrown.
+ /// Vista or above. If not a PlatformNotSupported exception will be thrown. If for some
+ /// reason the ETW Register call failed a NotSupported exception will be thrown.
/// </summary>
// <SecurityKernel Critical="True" Ring="0">
// <CallsSuppressUnmanagedCode Name="Interop.Advapi32.EventRegister(System.Guid&,Microsoft.Win32.Interop.Advapi32+EtwEnableCallback,System.Void*,System.Int64&):System.UInt32" />
}
//
- // implement Dispose Pattern to early deregister from ETW insted of waiting for
+ // implement Dispose Pattern to early deregister from ETW insted of waiting for
// the finalizer to call deregistration.
// Once the user is done with the provider it needs to call Close() or Dispose()
// If neither are called the finalizer will unregister the provider anyway
protected virtual void Dispose(bool disposing)
{
//
- // explicit cleanup is done by calling Dispose with true from
+ // explicit cleanup is done by calling Dispose with true from
// Dispose() or Close(). The disposing arguement is ignored because there
// are no unmanaged resources.
// The finalizer calls Dispose with false.
if (m_disposed)
return;
- // Disable the provider.
+ // Disable the provider.
m_enabled = false;
// Do most of the work under a lock to avoid shutdown race.
// Thus the ETW lock gets taken first and then our EventListenersLock gets taken
// in SendCommand(), and also here. If we called EventUnregister after taking
// the EventListenersLock then the take-lock order is reversed and we can have
- // deadlocks in race conditions (dispose racing with an ETW command).
- //
- // We solve by Unregistering after releasing the EventListenerLock.
+ // deadlocks in race conditions (dispose racing with an ETW command).
+ //
+ // We solve by Unregistering after releasing the EventListenerLock.
if (registrationHandle != 0)
EventUnregister(registrationHandle);
/// <summary>
/// This method deregisters the controlGuid of this class with ETW.
- ///
+ ///
/// </summary>
public virtual void Close()
{
void* callbackContext
)
{
- // This is an optional callback API. We will therefore ignore any failures that happen as a
+ // This is an optional callback API. We will therefore ignore any failures that happen as a
// result of turning on this provider as to not crash the app.
// EventSource has code to validate whether initialization it expected to occur actually occurred
try
command = ControllerCommand.SendManifest;
}
else
- return; // per spec you ignore commands you don't recognize.
+ return; // per spec you ignore commands you don't recognize.
if (!skipFinalOnControllerCommand)
OnControllerCommand(command, args, 0, 0);
private delegate void SessionInfoCallback(int etwSessionId, long matchAllKeywords, ref List<SessionInfo>? sessionList);
/// <summary>
- /// This method enumerates over all active ETW sessions that have enabled 'this.m_Guid'
+ /// This method enumerates over all active ETW sessions that have enabled 'this.m_Guid'
/// for the current process ID, calling 'action' for each session, and passing it the
/// ETW session and the 'AllKeywords' the session enabled for the current provider.
/// </summary>
private unsafe void GetSessionInfo(SessionInfoCallback action, ref List<SessionInfo>? sessionList)
{
- // We wish the EventSource package to be legal for Windows Store applications.
+ // We wish the EventSource package to be legal for Windows Store applications.
// Currently EnumerateTraceGuidsEx is not an allowed API, so we avoid its use here
// and use the information in the registry instead. This means that ETW controllers
- // that do not publish their intent to the registry (basically all controllers EXCEPT
- // TraceEventSesion) will not work properly
+ // that do not publish their intent to the registry (basically all controllers EXCEPT
+ // TraceEventSesion) will not work properly
// However the framework version of EventSource DOES have ES_SESSION_INFO defined and thus
- // does not have this issue.
+ // does not have this issue.
#if (PLATFORM_WINDOWS && (ES_SESSION_INFO || !ES_BUILD_STANDALONE))
- int buffSize = 256; // An initial guess that probably works most of the time.
+ int buffSize = 256; // An initial guess that probably works most of the time.
byte* buffer;
for (; ; )
{
#else
#if !ES_BUILD_PCL && PLATFORM_WINDOWS // TODO command arguments don't work on PCL builds...
// This code is only used in the Nuget Package Version of EventSource. because
- // the code above is using APIs baned from UWP apps.
- //
+ // the code above is using APIs baned from UWP apps.
+ //
// TODO: In addition to only working when TraceEventSession enables the provider, this code
- // also has a problem because TraceEvent does not clean up if the registry is stale
+ // also has a problem because TraceEvent does not clean up if the registry is stale
// It is unclear if it is worth keeping, but for now we leave it as it does work
- // at least some of the time.
+ // at least some of the time.
- // Determine our session from what is in the registry.
+ // Determine our session from what is in the registry.
string regKey = @"\Microsoft\Windows\CurrentVersion\Winevt\Publishers\{" + m_providerName + "}";
if (IntPtr.Size == 8)
regKey = @"Software" + @"\Wow6432Node" + regKey;
/// at the time the controller issues the command. To allow for providers to activate after the
/// controller issued a command, we also check the registry and use that to get the data. The function
/// returns an array of bytes representing the data, the index into that byte array where the data
- /// starts, and the command being issued associated with that data.
+ /// starts, and the command being issued associated with that data.
/// </summary>
private unsafe bool GetDataFromController(int etwSessionId,
Interop.Advapi32.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[]? data, out int dataStart)
data = key?.GetValue(valueName, null) as byte[];
if (data != null)
{
- // We only used the persisted data from the registry for updates.
+ // We only used the persisted data from the registry for updates.
command = ControllerCommand.Update;
return true;
}
Routine Description:
This routine is used by WriteEvent to unbox the object type and
- to fill the passed in ETW data descriptor.
+ to fill the passed in ETW data descriptor.
Arguments:
{
const long UTCMinTicks = 504911232000000000;
long dateTimeTicks = 0;
- // We cannot translate dates sooner than 1/1/1601 in UTC.
+ // We cannot translate dates sooner than 1/1/1601 in UTC.
// To avoid getting an ArgumentOutOfRangeException we compare with 1/1/1601 DateTime ticks
if (((DateTime)data).Ticks > UTCMinTicks)
dateTimeTicks = ((DateTime)data).ToFileTimeUtc();
else if (underlyingType == typeof(long))
data = (long)data;
else
- data = (int)Convert.ToInt64(data); // This handles all int/uint or below (we treat them like 32 bit ints)
+ data = (int)Convert.ToInt64(data); // This handles all int/uint or below (we treat them like 32 bit ints)
goto Again;
}
- catch { } // On wierd cases (e.g. enums of type double), give up and for compat simply tostring.
+ catch { } // On wierd cases (e.g. enums of type double), give up and for compat simply tostring.
}
// To our eyes, everything else is a just a string
/// WriteEvent, method to write a parameters with event schema properties
/// </summary>
/// <param name="eventDescriptor">
- /// Event Descriptor for this event.
+ /// Event Descriptor for this event.
/// </param>
/// <param name="activityID">
- /// A pointer to the activity ID GUID to log
+ /// A pointer to the activity ID GUID to log
/// </param>
/// <param name="childActivityID">
- /// childActivityID is marked as 'related' to the current activity ID.
+ /// childActivityID is marked as 'related' to the current activity ID.
/// </param>
/// <param name="eventPayload">
- /// Payload for the ETW event.
+ /// Payload for the ETW event.
/// </param>
// <SecurityKernel Critical="True" Ring="0">
// <CallsSuppressUnmanagedCode Name="Interop.Advapi32.EventWrite(System.Int64,EventDescriptor&,System.UInt32,System.Void*):System.UInt32" />
byte* currentBuffer = dataBuffer;
//
- // The loop below goes through all the arguments and fills in the data
+ // The loop below goes through all the arguments and fills in the data
// descriptors. For strings save the location in the dataString array.
// Calculates the total size of the event by adding the data descriptor
// size value set in EncodeObject method.
}
//
- // now fix any string arguments and set the pointer on the data descriptor
+ // now fix any string arguments and set the pointer on the data descriptor
//
fixed (char* v0 = (string?)dataRefObj[0], v1 = (string?)dataRefObj[1], v2 = (string?)dataRefObj[2], v3 = (string?)dataRefObj[3],
v4 = (string?)dataRefObj[4], v5 = (string?)dataRefObj[5], v6 = (string?)dataRefObj[6], v7 = (string?)dataRefObj[7])
/// WriteEvent, method to be used by generated code on a derived class
/// </summary>
/// <param name="eventDescriptor">
- /// Event Descriptor for this event.
+ /// Event Descriptor for this event.
/// </param>
/// <param name="activityID">
- /// A pointer to the activity ID to log
+ /// A pointer to the activity ID to log
/// </param>
/// <param name="childActivityID">
/// If this event is generating a child activity (WriteEventTransfer related activity) this is child activity
- /// This can be null for events that do not generate a child activity.
+ /// This can be null for events that do not generate a child activity.
/// </param>
/// <param name="dataCount">
- /// number of event descriptors
+ /// number of event descriptors
/// </param>
/// <param name="data">
/// pointer do the event data
// These are look-alikes to the Manifest based ETW OS APIs that have been shimmed to work
- // either with Manifest ETW or Classic ETW (if Manifest based ETW is not available).
+ // either with Manifest ETW or Classic ETW (if Manifest based ETW is not available).
private unsafe uint EventRegister(EventSource eventSource, Interop.Advapi32.EtwEnableCallback enableCallback)
{
m_providerName = eventSource.Name;
// See the LICENSE file in the project root for more information.
// This program uses code hyperlinks available as part of the HyperAddin Visual Studio plug-in.
-// It is available from http://www.codeplex.com/hyperAddin
+// It is available from http://www.codeplex.com/hyperAddin
#if ES_BUILD_STANDALONE
#define FEATURE_MANAGED_ETW_CHANNELS
// #define FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
// Basic Model
//
// PRINCIPLE: EventSource - ETW decoupling
-//
-// Conceptually an EventSouce is something that takes event logging data from the source methods
+//
+// Conceptually an EventSouce is something that takes event logging data from the source methods
// to the EventListener that can subscribe to them. Note that CONCEPTUALLY EVENTSOURCES DON'T
// KNOW ABOUT ETW!. The MODEL of the system is that there is a special EventListener which
// we will call the EtwEventListener, that forwards commands from ETW to EventSources and
// be that you DON'T NEED ETW.
//
// Now in actual practice, EventSouce have rather intimate knowledge of ETW and send events
-// to it directly, but this can be VIEWED AS AN OPTIMIZATION.
+// to it directly, but this can be VIEWED AS AN OPTIMIZATION.
//
// Basic Event Data Flow:
-//
+//
// There are two ways for event Data to enter the system
-// 1) WriteEvent* and friends. This is called the 'contract' based approach because
+// 1) WriteEvent* and friends. This is called the 'contract' based approach because
// you write a method per event which forms a contract that is know at compile time.
// In this scheme each event is given an EVENTID (small integer), which is its identity
-// 2) Write<T> methods. This is called the 'dynamic' approach because new events
+// 2) Write<T> methods. This is called the 'dynamic' approach because new events
// can be created on the fly. Event identity is determined by the event NAME, and these
// are not quite as efficient at runtime since you have at least a hash table lookup
-// on every event write.
+// on every event write.
//
// EventSource-EventListener transfer fully supports both ways of writing events (either contract
// based (WriteEvent*) or dynamic (Write<T>)). Both ways fully support the same set of data
-// types. It is recommended, however, that you use the contract based approach when the event scheme
+// types. It is recommended, however, that you use the contract based approach when the event scheme
// is known at compile time (that is whenever possible). It is more efficient, but more importantly
-// it makes the contract very explicit, and centralizes all policy about logging. These are good
+// it makes the contract very explicit, and centralizes all policy about logging. These are good
// things. The Write<T> API is really meant for more ad-hoc cases.
//
// Allowed Data:
-//
+//
// Note that EventSource-EventListeners have a conceptual serialization-deserialization that happens
-// during the transfer. In particular object identity is not preserved, some objects are morphed,
+// during the transfer. In particular object identity is not preserved, some objects are morphed,
// and not all data types are supported. In particular you can pass
-//
+//
// A Valid type to log to an EventSource include
// * Primitive data types
// * IEnumerable<T> of valid types T (this include arrays) (* New for V4.6)
// * Explicitly Opted in class or struct with public property Getters over Valid types. (* New for V4.6)
-//
-// This set of types is roughly a generalization of JSON support (basically primitives, bags, and arrays).
+//
+// This set of types is roughly a generalization of JSON support (basically primitives, bags, and arrays).
//
// Explicitly allowed structs include (* New for V4.6)
// * Marked with the EventData attribute
// * implicitly defined (e.g the C# new {x = 3, y = 5} syntax)
// * KeyValuePair<K,V> (thus dictionaries can be passed since they are an IEnumerable of KeyValuePair)
-//
-// When classes are returned in an EventListener, what is returned is something that implements
+//
+// When classes are returned in an EventListener, what is returned is something that implements
// IDictionary<string, T>. Thus when objects are passed to an EventSource they are transformed
-// into a key-value bag (the IDictionary<string, T>) for consumption in the listener. These
-// are obviously NOT the original objects.
-//
+// into a key-value bag (the IDictionary<string, T>) for consumption in the listener. These
+// are obviously NOT the original objects.
+//
// ETW serialization formats:
-//
-// As mentioned, conceptually EventSources send data to EventListeners and there is a conceptual
+//
+// As mentioned, conceptually EventSources send data to EventListeners and there is a conceptual
// copy/morph of that data as described above. In addition the .NET framework supports a conceptual
-// ETWListener that will send the data to the ETW stream. If you use this feature, the data needs
-// to be serialized in a way that ETW supports. ETW supports the following serialization formats
-//
-// 1) Manifest Based serialization.
+// ETWListener that will send the data to the ETW stream. If you use this feature, the data needs
+// to be serialized in a way that ETW supports. ETW supports the following serialization formats
+//
+// 1) Manifest Based serialization.
// 2) SelfDescribing serialization (TraceLogging style in the TraceLogging directory)
//
// A key factor is that the Write<T> method, which supports on the fly definition of events, can't
-// support the manifest based serialization because the manifest needs the schema of all events
+// support the manifest based serialization because the manifest needs the schema of all events
// to be known before any events are emitted. This implies the following:
//
// If you use Write<T> and the output goes to ETW it will use the SelfDescribing format.
// If you use the EventSource(string) constructor for an eventSource (in which you don't
// create a subclass), the default is also to use Self-Describing serialization. In addition
// you can use the EventSoruce(EventSourceSettings) constructor to also explicitly specify
-// Self-Describing serialization format. These affect the WriteEvent* APIs going to ETW.
+// Self-Describing serialization format. These affect the WriteEvent* APIs going to ETW.
+//
+// Note that none of this ETW serialization logic affects EventListeners. Only the ETW listener.
//
-// Note that none of this ETW serialization logic affects EventListeners. Only the ETW listener.
-//
// *************************************************************************************
// *** INTERNALS: Event Propagation
//
// Data enters the system either though
//
-// 1) A user defined method in the user defined subclass of EventSource which calls
-// A) A typesafe type specific overload of WriteEvent(ID, ...) e.g. WriteEvent(ID, string, string)
+// 1) A user defined method in the user defined subclass of EventSource which calls
+// A) A typesafe type specific overload of WriteEvent(ID, ...) e.g. WriteEvent(ID, string, string)
// * which calls into the unsafe WriteEventCore(ID COUNT EventData*) WriteEventWithRelatedActivityIdCore()
// B) The typesafe overload WriteEvent(ID, object[]) which calls the private helper WriteEventVarargs(ID, Guid* object[])
// C) Directly into the unsafe WriteEventCore(ID, COUNT EventData*) or WriteEventWithRelatedActivityIdCore()
//
-// All event data eventually flows to one of
-// * WriteEventWithRelatedActivityIdCore(ID, Guid*, COUNT, EventData*)
+// All event data eventually flows to one of
+// * WriteEventWithRelatedActivityIdCore(ID, Guid*, COUNT, EventData*)
// * WriteEventVarargs(ID, Guid*, object[])
//
-// 2) A call to one of the overloads of Write<T>. All these overloads end up in
+// 2) A call to one of the overloads of Write<T>. All these overloads end up in
// * WriteImpl<T>(EventName, Options, Data, Guid*, Guid*)
-//
+//
// On output there are the following routines
// Writing to all listeners that are NOT ETW, we have the following routines
// * WriteToAllListeners(ID, Guid*, Guid*, COUNT, EventData*)
// * WriteToAllListeners(NAME, Guid*, Guid*, EventPayload)
//
// EventPayload is the internal type that implements the IDictionary<string, object> interface
-// The EventListeners will pass back for serialized classes for nested object, but
+// The EventListeners will pass back for serialized classes for nested object, but
// WriteToAllListeners(NAME, Guid*, Guid*, EventPayload) unpacks this and uses the fields as if they
-// were parameters to a method.
-//
-// The first two are used for the WriteEvent* case, and the later is used for the Write<T> case.
-//
-// Writing to ETW, Manifest Based
+// were parameters to a method.
+//
+// The first two are used for the WriteEvent* case, and the later is used for the Write<T> case.
+//
+// Writing to ETW, Manifest Based
// EventProvider.WriteEvent(EventDescriptor, Guid*, COUNT, EventData*)
// EventProvider.WriteEvent(EventDescriptor, Guid*, object[])
// Writing to ETW, Self-Describing format
// WriteMultiMerge(NAME, Options, Types, EventData*)
// WriteMultiMerge(NAME, Options, Types, object[])
-// WriteImpl<T> has logic that knows how to serialize (like WriteMultiMerge) but also knows
-// where it will write it to
+// WriteImpl<T> has logic that knows how to serialize (like WriteMultiMerge) but also knows
+// where it will write it to
//
// All ETW writes eventually call
// EventWriteTransfer
// WriteImpl<T>
// EventProvider.WriteEvent(EventDescriptor, Guid*, COUNT, EventData*)
// EventProvider.WriteEvent(EventDescriptor, Guid*, object[])
-//
+//
// Serialization: We have a bit of a hodge-podge of serializers right now. Only the one for ETW knows
// how to deal with nested classes or arrays. I will call this serializer the 'TypeInfo' serializer
// since it is the TraceLoggingTypeInfo structure that knows how to do this. Effectively for a type you
-// can call one of these
+// can call one of these
// WriteMetadata - transforms the type T into serialization meta data blob for that type
// WriteObjectData - transforms an object of T into serialization data blob for that instance
-// GetData - transforms an object of T into its deserialized form suitable for passing to EventListener.
-// The first two are used to serialize something for ETW. The second one is used to transform the object
+// GetData - transforms an object of T into its deserialized form suitable for passing to EventListener.
+// The first two are used to serialize something for ETW. The second one is used to transform the object
// for use by the EventListener. We also have a 'DecodeObject' method that will take a EventData* and
-// deserialize to pass to an EventListener, but it only works on primitive types (types supported in version V4.5).
-//
-// It is an important observation that while EventSource does support users directly calling with EventData*
+// deserialize to pass to an EventListener, but it only works on primitive types (types supported in version V4.5).
+//
+// It is an important observation that while EventSource does support users directly calling with EventData*
// blobs, we ONLY support that for the primitive types (V4.5 level support). Thus while there is a EventData*
-// path through the system it is only for some types. The object[] path is the more general (but less efficient) path.
+// path through the system it is only for some types. The object[] path is the more general (but less efficient) path.
//
-// TODO There is cleanup needed There should be no divergence until WriteEventRaw.
-//
-// TODO: We should have a single choke point (right now we always have this parallel EventData* and object[] path. This
-// was historical (at one point we tried to pass object directly from EventSoruce to EventListener. That was always
+// TODO There is cleanup needed There should be no divergence until WriteEventRaw.
+//
+// TODO: We should have a single choke point (right now we always have this parallel EventData* and object[] path. This
+// was historical (at one point we tried to pass object directly from EventSoruce to EventListener. That was always
// fragile and a compatibility headache, but we have finally been forced into the idea that there is always a transformation.
// This allows us to use the EventData* form to be the canonical data format in the low level APIs. This also gives us the
-// opportunity to expose this format to EventListeners in the future.
-//
+// opportunity to expose this format to EventListeners in the future.
+//
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
{
/// <summary>
/// This class is meant to be inherited by a user-defined event source in order to define a managed
- /// ETW provider. Please See DESIGN NOTES above for the internal architecture.
+ /// ETW provider. Please See DESIGN NOTES above for the internal architecture.
/// The minimal definition of an EventSource simply specifies a number of ETW event methods that
- /// call one of the EventSource.WriteEvent overloads, <see cref="EventSource.WriteEventCore"/>,
- /// or <see cref="EventSource.WriteEventWithRelatedActivityIdCore"/> to log them. This functionality
+ /// call one of the EventSource.WriteEvent overloads, <see cref="EventSource.WriteEventCore"/>,
+ /// or <see cref="EventSource.WriteEventWithRelatedActivityIdCore"/> to log them. This functionality
/// is sufficient for many users.
/// <para>
- /// To achieve more control over the ETW provider manifest exposed by the event source type, the
+ /// To achieve more control over the ETW provider manifest exposed by the event source type, the
/// [<see cref="EventAttribute"/>] attributes can be specified for the ETW event methods.
/// </para><para>
/// For very advanced EventSources, it is possible to intercept the commands being given to the
- /// eventSource and change what filtering is done (see EventListener.EnableEvents and
- /// <see cref="EventListener.DisableEvents"/>) or cause actions to be performed by the eventSource,
+ /// eventSource and change what filtering is done (see EventListener.EnableEvents and
+ /// <see cref="EventListener.DisableEvents"/>) or cause actions to be performed by the eventSource,
/// e.g. dumping a data structure (see EventSource.SendCommand and
/// <see cref="EventSource.OnEventCommand"/>).
/// </para><para>
- /// The eventSources can be turned on with Windows ETW controllers (e.g. logman), immediately.
- /// It is also possible to control and intercept the data dispatcher programmatically. See
+ /// The eventSources can be turned on with Windows ETW controllers (e.g. logman), immediately.
+ /// It is also possible to control and intercept the data dispatcher programmatically. See
/// <see cref="EventListener"/> for more.
/// </para>
/// </summary>
/// </summary>
public string Name { get { return m_name; } }
/// <summary>
- /// Every eventSource is assigned a GUID to uniquely identify it to the system.
+ /// Every eventSource is assigned a GUID to uniquely identify it to the system.
/// </summary>
public Guid Guid { get { return m_guid; } }
}
/// <summary>
- /// Returns true if events with greater than or equal 'level' and have one of 'keywords' set are enabled.
- ///
+ /// Returns true if events with greater than or equal 'level' and have one of 'keywords' set are enabled.
+ ///
/// Note that the result of this function is only an approximation on whether a particular
/// event is active or not. It is only meant to be used as way of avoiding expensive
/// computation for logging when logging is not on, therefore it sometimes returns false
- /// positives (but is always accurate when returning false). EventSources are free to
- /// have additional filtering.
+ /// positives (but is always accurate when returning false). EventSources are free to
+ /// have additional filtering.
/// </summary>
[SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
public bool IsEnabled(EventLevel level, EventKeywords keywords)
/// <summary>
/// Returns true if events with greater than or equal 'level' and have one of 'keywords' set are enabled, or
/// if 'keywords' specifies a channel bit for a channel that is enabled.
- ///
+ ///
/// Note that the result of this function only an approximation on whether a particular
/// event is active or not. It is only meant to be used as way of avoiding expensive
/// computation for logging when logging is not on, therefore it sometimes returns false
- /// positives (but is always accurate when returning false). EventSources are free to
- /// have additional filtering.
+ /// positives (but is always accurate when returning false). EventSources are free to
+ /// have additional filtering.
/// </summary>
[SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
public bool IsEnabled(EventLevel level, EventKeywords keywords, EventChannel channel)
get { return m_config; }
}
- // Manifest support
+ // Manifest support
/// <summary>
- /// Returns the GUID that uniquely identifies the eventSource defined by 'eventSourceType'.
- /// This API allows you to compute this without actually creating an instance of the EventSource.
- /// It only needs to reflect over the type.
+ /// Returns the GUID that uniquely identifies the eventSource defined by 'eventSourceType'.
+ /// This API allows you to compute this without actually creating an instance of the EventSource.
+ /// It only needs to reflect over the type.
/// </summary>
public static Guid GetGuid(Type eventSourceType)
{
{
throw new ArgumentException(SR.Argument_InvalidTypeName, nameof(eventSourceType));
}
- return GenerateGuidFromName(name.ToUpperInvariant()); // Make it case insensitive.
+ return GenerateGuidFromName(name.ToUpperInvariant()); // Make it case insensitive.
}
/// <summary>
- /// Returns the official ETW Provider name for the eventSource defined by 'eventSourceType'.
- /// This API allows you to compute this without actually creating an instance of the EventSource.
- /// It only needs to reflect over the type.
+ /// Returns the official ETW Provider name for the eventSource defined by 'eventSourceType'.
+ /// This API allows you to compute this without actually creating an instance of the EventSource.
+ /// It only needs to reflect over the type.
/// </summary>
public static string GetName(Type eventSourceType)
{
// EventListener support
/// <summary>
- /// returns a list (IEnumerable) of all sources in the appdomain). EventListeners typically need this.
+ /// returns a list (IEnumerable) of all sources in the appdomain). EventListeners typically need this.
/// </summary>
/// <returns></returns>
public static IEnumerable<EventSource> GetSources()
/// <summary>
/// Send a command to a particular EventSource identified by 'eventSource'.
/// Calling this routine simply forwards the command to the EventSource.OnEventCommand
- /// callback. What the EventSource does with the command and its arguments are from
- /// that point EventSource-specific.
+ /// callback. What the EventSource does with the command and its arguments are from
+ /// that point EventSource-specific.
/// </summary>
/// <param name="eventSource">The instance of EventSource to send the command to</param>
/// <param name="command">A positive user-defined EventCommand, or EventCommand.SendManifest</param>
// Error APIs. (We don't throw by default, but you can probe for status)
/// <summary>
/// Because
- ///
+ ///
/// 1) Logging is often optional and thus should not generate fatal errors (exceptions)
/// 2) EventSources are often initialized in class constructors (which propagate exceptions poorly)
- ///
- /// The event source constructor does not throw exceptions. Instead we remember any exception that
+ ///
+ /// The event source constructor does not throw exceptions. Instead we remember any exception that
/// was generated (it is also logged to Trace.WriteLine).
/// </summary>
public Exception? ConstructionException { get { return m_constructionException; } }
/// <summary>
- /// EventSources can have arbitrary string key-value pairs associated with them called Traits.
+ /// EventSources can have arbitrary string key-value pairs associated with them called Traits.
/// These traits are not interpreted by the EventSource but may be interpreted by EventListeners
- /// (e.g. like the built in ETW listener). These traits are specified at EventSource
- /// construction time and can be retrieved by using this GetTrait API.
+ /// (e.g. like the built in ETW listener). These traits are specified at EventSource
+ /// construction time and can be retrieved by using this GetTrait API.
/// </summary>
/// <param name="key">The key to look up in the set of key-value pairs passed to the EventSource constructor</param>
/// <returns>The value string associated with key. Will return null if there is no such key.</returns>
}
/// <summary>
- /// Displays the name and GUID for the eventSource for debugging purposes.
+ /// Displays the name and GUID for the eventSource for debugging purposes.
/// </summary>
public override string ToString()
{
}
/// <summary>
- /// Fires when a Command (e.g. Enable) comes from a an EventListener.
+ /// Fires when a Command (e.g. Enable) comes from a an EventListener.
/// </summary>
public event EventHandler<EventCommandEventArgs>? EventCommandExecuted
{
#region ActivityID
/// <summary>
- /// When a thread starts work that is on behalf of 'something else' (typically another
+ /// When a thread starts work that is on behalf of 'something else' (typically another
/// thread or network request) it should mark the thread as working on that other work.
/// This API marks the current thread as working on activity 'activityID'. This API
/// should be used when the caller knows the thread's current activity (the one being
/// overwritten) has completed. Otherwise, callers should prefer the overload that
/// return the oldActivityThatWillContinue (below).
- ///
- /// All events created with the EventSource on this thread are also tagged with the
- /// activity ID of the thread.
- ///
+ ///
+ /// All events created with the EventSource on this thread are also tagged with the
+ /// activity ID of the thread.
+ ///
/// It is common, and good practice after setting the thread to an activity to log an event
- /// with a 'start' opcode to indicate that precise time/thread where the new activity
+ /// with a 'start' opcode to indicate that precise time/thread where the new activity
/// started.
/// </summary>
- /// <param name="activityId">A Guid that represents the new activity with which to mark
+ /// <param name="activityId">A Guid that represents the new activity with which to mark
/// the current thread</param>
public static void SetCurrentThreadActivityId(Guid activityId)
{
TplEventSource.Log.SetActivityId(activityId);
// We ignore errors to keep with the convention that EventSources do not throw errors.
- // Note we can't access m_throwOnWrites because this is a static method.
+ // Note we can't access m_throwOnWrites because this is a static method.
#if FEATURE_MANAGED_ETW
#if FEATURE_PERFTRACING
// Set the activity id via EventPipe.
{
get
{
- // We ignore errors to keep with the convention that EventSources do not throw
+ // We ignore errors to keep with the convention that EventSources do not throw
// errors. Note we can't access m_throwOnWrites because this is a static method.
Guid retVal = new Guid();
#if FEATURE_MANAGED_ETW
}
/// <summary>
- /// When a thread starts work that is on behalf of 'something else' (typically another
+ /// When a thread starts work that is on behalf of 'something else' (typically another
/// thread or network request) it should mark the thread as working on that other work.
- /// This API marks the current thread as working on activity 'activityID'. It returns
+ /// This API marks the current thread as working on activity 'activityID'. It returns
/// whatever activity the thread was previously marked with. There is a convention that
- /// callers can assume that callees restore this activity mark before the callee returns.
+ /// callers can assume that callees restore this activity mark before the callee returns.
/// To encourage this, this API returns the old activity, so that it can be restored later.
- ///
- /// All events created with the EventSource on this thread are also tagged with the
- /// activity ID of the thread.
- ///
+ ///
+ /// All events created with the EventSource on this thread are also tagged with the
+ /// activity ID of the thread.
+ ///
/// It is common, and good practice after setting the thread to an activity to log an event
- /// with a 'start' opcode to indicate that precise time/thread where the new activity
+ /// with a 'start' opcode to indicate that precise time/thread where the new activity
/// started.
/// </summary>
- /// <param name="activityId">A Guid that represents the new activity with which to mark
+ /// <param name="activityId">A Guid that represents the new activity with which to mark
/// the current thread</param>
- /// <param name="oldActivityThatWillContinue">The Guid that represents the current activity
+ /// <param name="oldActivityThatWillContinue">The Guid that represents the current activity
/// which will continue at some point in the future, on the current thread</param>
public static void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue)
{
oldActivityThatWillContinue = activityId;
#if FEATURE_MANAGED_ETW
// We ignore errors to keep with the convention that EventSources do not throw errors.
- // Note we can't access m_throwOnWrites because this is a static method.
+ // Note we can't access m_throwOnWrites because this is a static method.
#if FEATURE_PERFTRACING && PLATFORM_WINDOWS
EventPipeInternal.EventActivityIdControl(
#endif // FEATURE_MANAGED_ETW
// We don't call the activityDying callback here because the caller has declared that
- // it is not dying.
+ // it is not dying.
if (TplEventSource.Log != null)
TplEventSource.Log.SetActivityId(activityId);
}
#region protected
/// <summary>
- /// This is the constructor that most users will use to create their eventSource. It takes
- /// no parameters. The ETW provider name and GUID of the EventSource are determined by the EventSource
+ /// This is the constructor that most users will use to create their eventSource. It takes
+ /// no parameters. The ETW provider name and GUID of the EventSource are determined by the EventSource
/// custom attribute (so you can determine these things declaratively). If the GUID for the eventSource
/// is not specified in the EventSourceAttribute (recommended), it is Generated by hashing the name.
/// If the ETW provider name of the EventSource is not given, the name of the EventSource class is used as
}
/// <summary>
- /// By default calling the 'WriteEvent' methods do NOT throw on errors (they silently discard the event).
+ /// By default calling the 'WriteEvent' methods do NOT throw on errors (they silently discard the event).
/// This is because in most cases users assume logging is not 'precious' and do NOT wish to have logging failures
/// crash the program. However for those applications where logging is 'precious' and if it fails the caller
/// wishes to react, setting 'throwOnEventWriteErrors' will cause an exception to be thrown if WriteEvent
/// fails. Note the fact that EventWrite succeeds does not necessarily mean that the event reached its destination
/// only that operation of writing it did not fail. These EventSources will not generate self-describing ETW events.
- ///
- /// For compatibility only use the EventSourceSettings.ThrowOnEventWriteErrors flag instead.
+ ///
+ /// For compatibility only use the EventSourceSettings.ThrowOnEventWriteErrors flag instead.
/// </summary>
// [Obsolete("Use the EventSource(EventSourceSettings) overload")]
protected EventSource(bool throwOnEventWriteErrors)
{ }
/// <summary>
- /// Construct an EventSource with additional non-default settings (see EventSourceSettings for more)
+ /// Construct an EventSource with additional non-default settings (see EventSourceSettings for more)
/// </summary>
protected EventSource(EventSourceSettings settings) : this(settings, null) { }
/// <summary>
- /// Construct an EventSource with additional non-default settings.
- ///
- /// Also specify a list of key-value pairs called traits (you must pass an even number of strings).
+ /// Construct an EventSource with additional non-default settings.
+ ///
+ /// Also specify a list of key-value pairs called traits (you must pass an even number of strings).
/// The first string is the key and the second is the value. These are not interpreted by EventSource
- /// itself but may be interpreted the listeners. Can be fetched with GetTrait(string).
+ /// itself but may be interpreted the listeners. Can be fetched with GetTrait(string).
/// </summary>
/// <param name="settings">See EventSourceSettings for more.</param>
/// <param name="traits">A collection of key-value strings (must be an even number).</param>
}
/// <summary>
- /// This method is called when the eventSource is updated by the controller.
+ /// This method is called when the eventSource is updated by the controller.
/// </summary>
protected virtual void OnEventCommand(EventCommandEventArgs command) { }
descrs[0].DataPointer = (IntPtr)(&blobSize);
descrs[0].Size = 4;
descrs[0].Reserved = 0;
- descrs[1].DataPointer = (IntPtr)(&blobSize); // valid address instead of empty content
+ descrs[1].DataPointer = (IntPtr)(&blobSize); // valid address instead of empty content
descrs[1].Size = 0;
descrs[1].Reserved = 0;
WriteEventCore(eventId, 2, descrs);
descrs[1].DataPointer = (IntPtr)(&blobSize);
descrs[1].Size = 4;
descrs[1].Reserved = 0;
- descrs[2].DataPointer = (IntPtr)(&blobSize); // valid address instead of empty contents
+ descrs[2].DataPointer = (IntPtr)(&blobSize); // valid address instead of empty contents
descrs[2].Size = 0;
descrs[2].Reserved = 0;
WriteEventCore(eventId, 3, descrs);
}
//Important, we pass this structure directly to the Win32 EventWrite API, so this structure must be layed out exactly
- // the way EventWrite wants it.
+ // the way EventWrite wants it.
internal ulong m_Ptr;
internal int m_Size;
#pragma warning disable 0649
}
/// <summary>
- /// This routine allows you to create efficient WriteEventWithRelatedActivityId helpers, however the code
+ /// This routine allows you to create efficient WriteEventWithRelatedActivityId helpers, however the code
/// that you use to do this, while straightforward, is unsafe. The only difference from
/// <see cref="WriteEventCore"/> is that you pass the relatedActivityId from caller through to this API
/// </summary>
}
}
- // fallback varags helpers.
+ // fallback varags helpers.
/// <summary>
/// This is the varargs helper for writing an event. It does create an array and box all the arguments so it is
/// relatively inefficient and should only be used for relatively rare events (e.g. less than 100 / sec). If your
- /// rates are faster than that you should use <see cref="WriteEventCore"/> to create fast helpers for your particular
- /// method signature. Even if you use this for rare events, this call should be guarded by an <see cref="IsEnabled()"/>
- /// check so that the varargs call is not made when the EventSource is not active.
+ /// rates are faster than that you should use <see cref="WriteEventCore"/> to create fast helpers for your particular
+ /// method signature. Even if you use this for rare events, this call should be guarded by an <see cref="IsEnabled()"/>
+ /// check so that the varargs call is not made when the EventSource is not active.
/// </summary>
[SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
protected unsafe void WriteEvent(int eventId, params object?[] args)
/// This is the varargs helper for writing an event which also specifies a related activity. It is completely analogous
/// to corresponding WriteEvent (they share implementation). It does create an array and box all the arguments so it is
/// relatively inefficient and should only be used for relatively rare events (e.g. less than 100 / sec). If your
- /// rates are faster than that you should use <see cref="WriteEventWithRelatedActivityIdCore"/> to create fast helpers for your
+ /// rates are faster than that you should use <see cref="WriteEventWithRelatedActivityIdCore"/> to create fast helpers for your
/// particular method signature. Even if you use this for rare events, this call should be guarded by an <see cref="IsEnabled()"/>
/// check so that the varargs call is not made when the EventSource is not active.
/// </summary>
SendManifest(m_rawManifest);
}
catch (Exception)
- { } // If it fails, simply give up.
+ { } // If it fails, simply give up.
m_eventSourceEnabled = false;
}
if (m_etwProvider != null)
/// <summary>
/// This method is responsible for the common initialization path from our constructors. It must
- /// not leak any exceptions (otherwise, since most EventSource classes define a static member,
+ /// not leak any exceptions (otherwise, since most EventSource classes define a static member,
/// "Log", such an exception would become a cached exception for the initialization of the static
/// member, and any future access to the "Log" would throw the cached exception).
/// </summary>
m_activityTracker = ActivityTracker.Instance;
#if FEATURE_MANAGED_ETW || FEATURE_PERFTRACING
- // Create and register our provider traits. We do this early because it is needed to log errors
- // In the self-describing event case.
+ // Create and register our provider traits. We do this early because it is needed to log errors
+ // In the self-describing event case.
this.InitializeProviderMetadata();
#endif
#if FEATURE_MANAGED_ETW
eventPipeProvider.Register(this);
}
#endif
- // Add the eventSource to the global (weak) list.
- // This also sets m_id, which is the index in the list.
+ // Add the eventSource to the global (weak) list.
+ // This also sets m_id, which is the index in the list.
EventListener.AddEventSource(this);
#if FEATURE_MANAGED_ETW
- // OK if we get this far without an exception, then we can at least write out error messages.
- // Set m_provider, which allows this.
+ // OK if we get this far without an exception, then we can at least write out error messages.
+ // Set m_provider, which allows this.
m_etwProvider = etwProvider;
#if PLATFORM_WINDOWS
#if FEATURE_PERFTRACING
m_eventPipeProvider = eventPipeProvider;
#endif
- Debug.Assert(!m_eventSourceEnabled); // We can't be enabled until we are completely initted.
- // We are logically completely initialized at this point.
+ Debug.Assert(!m_eventSourceEnabled); // We can't be enabled until we are completely initted.
+ // We are logically completely initialized at this point.
m_completelyInited = true;
}
catch (Exception e)
ReportOutOfBandMessage("ERROR: Exception during construction of EventSource " + Name + ": " + e.Message, true);
}
- // Once m_completelyInited is set, you can have concurrency, so all work is under the lock.
+ // Once m_completelyInited is set, you can have concurrency, so all work is under the lock.
lock (EventListener.EventListenersLock)
{
- // If there are any deferred commands, we can do them now.
- // This is the most likely place for exceptions to happen.
- // Note that we are NOT resetting m_deferredCommands to NULL here,
+ // If there are any deferred commands, we can do them now.
+ // This is the most likely place for exceptions to happen.
+ // Note that we are NOT resetting m_deferredCommands to NULL here,
// We are giving for EventHandler<EventCommandEventArgs> that will be attached later
EventCommandEventArgs? deferredCommands = m_deferredCommands;
while (deferredCommands != null)
{
- DoCommand(deferredCommands); // This can never throw, it catches them and reports the errors.
+ DoCommand(deferredCommands); // This can never throw, it catches them and reports the errors.
deferredCommands = deferredCommands.nextCommand;
}
}
private unsafe object? DecodeObject(int eventId, int parameterId, ref EventSource.EventData* data)
{
// TODO FIX : We use reflection which in turn uses EventSource, right now we carefully avoid
- // the recursion, but can we do this in a robust way?
+ // the recursion, but can we do this in a robust way?
IntPtr dataPointer = data->DataPointer;
// advance to next EventData in array
}
// Finds the Dispatcher (which holds the filtering state), for a given dispatcher for the current
- // eventSource).
+ // eventSource).
private EventDispatcher? GetDispatcher(EventListener? listener)
{
EventDispatcher? dispatcher = m_Dispatchers;
{
if (m_eventSourceEnabled)
{
- Debug.Assert(m_eventData != null); // You must have initialized this if you enabled the source.
+ Debug.Assert(m_eventData != null); // You must have initialized this if you enabled the source.
try
{
if (childActivityID != null)
{
ValidateEventOpcodeForTransfer(ref m_eventData[eventId], m_eventData[eventId].Name);
- // If you use WriteEventWithRelatedActivityID you MUST declare the first argument to be a GUID
- // with the name 'relatedActivityID, and NOT pass this argument to the WriteEvent method.
+ // If you use WriteEventWithRelatedActivityID you MUST declare the first argument to be a GUID
+ // with the name 'relatedActivityID, and NOT pass this argument to the WriteEvent method.
// During manifest creation we modify the ParameterInfo[] that we store to strip out any
// first parameter that is of type Guid and named "relatedActivityId." Thus, if you call
// WriteEventWithRelatedActivityID from a method that doesn't name its first parameter correctly
}
/// <summary>
- /// We expect that the arguments to the Event method and the arguments to WriteEvent match. This function
+ /// We expect that the arguments to the Event method and the arguments to WriteEvent match. This function
/// checks that they in fact match and logs a warning to the debugger if they don't.
/// </summary>
/// <param name="infos"></param>
private void LogEventArgsMismatches(ParameterInfo[] infos, object?[] args)
{
#if (!ES_BUILD_PCL && !ES_BUILD_PN)
- // It would be nice to have this on PCL builds, but it would be pointless since there isn't support for
+ // It would be nice to have this on PCL builds, but it would be pointless since there isn't support for
// writing to the debugger log on PCL.
bool typesMatch = args.Length == infos.Length;
Type? argType = args[i]?.GetType();
// Checking to see if the Parameter types (from the Event method) match the supplied argument types.
- // Fail if one of two things hold : either the argument type is not equal or assignable to the parameter type, or the
+ // Fail if one of two things hold : either the argument type is not equal or assignable to the parameter type, or the
// argument is null and the parameter type is a non-Nullable<T> value type.
if ((args[i] != null && !pType.IsAssignableFrom(argType))
|| (args[i] == null && !((pType.IsGenericType && pType.GetGenericTypeDefinition() == typeof(Nullable<>)) || !pType.IsValueType)))
args: args);
}
- // helper for writing to all EventListeners attached the current eventSource.
+ // helper for writing to all EventListeners attached the current eventSource.
internal unsafe void WriteToAllListeners(int eventId, uint* osThreadId, DateTime* timeStamp, Guid* activityID, Guid* childActivityID, params object?[] args)
{
EventWrittenEventArgs eventCallbackArgs = new EventWrittenEventArgs(this);
}
else
{
- // We want the name of the provider to show up so if we don't have a manifest we create
- // on that at least has the provider name (I don't define any events).
+ // We want the name of the provider to show up so if we don't have a manifest we create
+ // on that at least has the provider name (I don't define any events).
if (m_rawManifest == null && m_outOfBandMessageCount == 1)
{
ManifestBuilder manifestBuilder = new ManifestBuilder(Name, Guid, Name, null, EventManifestOptions.None);
SendManifest(manifestBuilder.CreateManifest());
}
- // We use this low level routine to bypass the enabled checking, since the eventSource itself is only partially inited.
+ // We use this low level routine to bypass the enabled checking, since the eventSource itself is only partially inited.
fixed (char* msgStringPtr = msgString)
{
EventDescriptor descr = new EventDescriptor(0, 0, 0, (byte)level, 0, 0, keywords);
}
/// <summary>
- /// Since this is a means of reporting errors (see ReportoutOfBandMessage) any failure encountered
+ /// Since this is a means of reporting errors (see ReportoutOfBandMessage) any failure encountered
/// while writing the message to any one of the listeners will be silently ignored.
/// </summary>
private void WriteStringToAllListeners(string eventName, string msg)
if (dispatcher.m_EventEnabled == null)
{
// if the listeners that weren't correctly initialized, we will send to it
- // since this is an error message and we want to see it go out.
+ // since this is an error message and we want to see it go out.
dispatcherEnabled = true;
}
else
/// <summary>
/// Returns true if 'eventNum' is enabled if you only consider the level and matchAnyKeyword filters.
- /// It is possible that eventSources turn off the event based on additional filtering criteria.
+ /// It is possible that eventSources turn off the event based on additional filtering criteria.
/// </summary>
private bool IsEnabledByDefault(int eventNum, bool enable, EventLevel currentLevel, EventKeywords currentMatchAnyKeyword)
{
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
private void ThrowEventSourceException(string? eventName, Exception? innerEx = null)
{
- // If we fail during out of band logging we may end up trying
- // to throw another EventSourceException, thus hitting a StackOverflowException.
+ // If we fail during out of band logging we may end up trying
+ // to throw another EventSourceException, thus hitting a StackOverflowException.
// Avoid StackOverflow by making sure we do not recursively call this method.
if (m_EventSourceExceptionRecurenceCount > 0)
return;
#if FEATURE_MANAGED_ETW
/// <summary>
- /// This class lets us hook the 'OnEventCommand' from the eventSource.
+ /// This class lets us hook the 'OnEventCommand' from the eventSource.
/// </summary>
private class OverideEventProvider : EventProvider
{
protected override void OnControllerCommand(ControllerCommand command, IDictionary<string, string?>? arguments,
int perEventSourceSessionId, int etwSessionId)
{
- // We use null to represent the ETW EventListener.
+ // We use null to represent the ETW EventListener.
EventListener? listener = null;
m_eventSource.SendCommand(listener, m_eventProviderType, perEventSourceSessionId, etwSessionId,
(EventCommand)command, IsEnabled(), Level, MatchAnyKeyword, arguments);
/// <summary>
/// Used to hold all the static information about an event. This includes everything in the event
/// descriptor as well as some stuff we added specifically for EventSource. see the
- /// code:m_eventData for where we use this.
+ /// code:m_eventData for where we use this.
/// </summary>
/*
- EventMetadata was public in the separate System.Diagnostics.Tracing assembly(pre NS2.0),
+ EventMetadata was public in the separate System.Diagnostics.Tracing assembly(pre NS2.0),
now the move to CoreLib marked them as private.
- While they are technically private (it's a contract used between the library and the ILC toolchain),
+ While they are technically private (it's a contract used between the library and the ILC toolchain),
we need them to be rooted and exported from shared library for the system to work.
- For now I'm simply marking them as public again.A cleaner solution might be to use.rd.xml to
+ For now I'm simply marking them as public again.A cleaner solution might be to use.rd.xml to
root them and modify shared library definition to force export them.
*/
#if ES_BUILD_PN
public byte TriggersActivityTracking; // count of listeners that marked this event as trigger for start of activity logging.
#pragma warning restore 0649
public string Name; // the name of the event
- public string? Message; // If the event has a message associated with it, this is it.
- public ParameterInfo[] Parameters; // TODO can we remove?
+ public string? Message; // If the event has a message associated with it, this is it.
+ public ParameterInfo[] Parameters; // TODO can we remove?
public TraceLoggingEventTypes? TraceLoggingEventTypes;
public EventActivityOptions ActivityOptions;
// This is the internal entry point that code:EventListeners call when wanting to send a command to a
// eventSource. The logic is as follows
- //
+ //
// * if Command == Update
- // * perEventSourceSessionId specifies the per-provider ETW session ID that the command applies
+ // * perEventSourceSessionId specifies the per-provider ETW session ID that the command applies
// to (if listener != null)
// perEventSourceSessionId = 0 - reserved for EventListeners
// perEventSourceSessionId = 1..SessionMask.MAX - reserved for activity tracing aware ETW sessions
- // perEventSourceSessionId-1 represents the bit in the reserved field (bits 44..47) in
+ // perEventSourceSessionId-1 represents the bit in the reserved field (bits 44..47) in
// Keywords that identifies the session
- // perEventSourceSessionId = SessionMask.MAX+1 - reserved for legacy ETW sessions; these are
+ // perEventSourceSessionId = SessionMask.MAX+1 - reserved for legacy ETW sessions; these are
// discriminated by etwSessionId
// * etwSessionId specifies a machine-wide ETW session ID; this allows correlation of
// activity tracing across different providers (which might have different sessionIds
// for the same ETW session)
// * enable, level, matchAnyKeywords are used to set a default for all events for the
// eventSource. In particular, if 'enabled' is false, 'level' and
- // 'matchAnyKeywords' are not used.
+ // 'matchAnyKeywords' are not used.
// * OnEventCommand is invoked, which may cause calls to
// code:EventSource.EnableEventForDispatcher which may cause changes in the filtering
// depending on the logic in that routine.
// * else (command != Update)
// * Simply call OnEventCommand. The expectation is that filtering is NOT changed.
- // * The 'enabled' 'level', matchAnyKeyword' arguments are ignored (must be true, 0, 0).
- //
+ // * The 'enabled' 'level', matchAnyKeyword' arguments are ignored (must be true, 0, 0).
+ //
// dispatcher == null has special meaning. It is the 'ETW' dispatcher.
internal void SendCommand(EventListener? listener, EventProviderType eventProviderType, int perEventSourceSessionId, int etwSessionId,
EventCommand command, bool enable,
{
// After the first command arrive after construction, we are ready to get rid of the deferred commands
this.m_deferredCommands = null;
- // We are fully initialized, do the command
+ // We are fully initialized, do the command
DoCommand(commandArgs);
}
else
{
- // We can't do the command, simply remember it and we do it when we are fully constructed.
+ // We can't do the command, simply remember it and we do it when we are fully constructed.
if (m_deferredCommands == null)
m_deferredCommands = commandArgs; // create the first entry
else
{
- // We have one or more entries, find the last one and add it to that.
+ // We have one or more entries, find the last one and add it to that.
EventCommandEventArgs lastCommand = m_deferredCommands;
while (lastCommand.nextCommand != null)
lastCommand = lastCommand.nextCommand;
}
/// <summary>
- /// We want the eventSource to be fully initialized when we do commands because that way we can send
+ /// We want the eventSource to be fully initialized when we do commands because that way we can send
/// error messages and other logging directly to the event stream. Unfortunately we can get callbacks
- /// when we are not fully initialized. In that case we store them in 'commandArgs' and do them later.
- /// This helper actually does all actual command logic.
+ /// when we are not fully initialized. In that case we store them in 'commandArgs' and do them later.
+ /// This helper actually does all actual command logic.
/// </summary>
internal void DoCommand(EventCommandEventArgs commandArgs)
{
// PRECONDITION: We should be holding the EventListener.EventListenersLock
- // We defer commands until we are completely inited. This allows error messages to be sent.
+ // We defer commands until we are completely inited. This allows error messages to be sent.
Debug.Assert(m_completelyInited);
#if FEATURE_MANAGED_ETW
{
if (!m_eventSourceEnabled)
{
- // EventSource turned on for the first time, simply copy the bits.
+ // EventSource turned on for the first time, simply copy the bits.
m_level = commandArgs.level;
m_matchAnyKeyword = commandArgs.matchAnyKeyword;
}
}
}
- // interpret perEventSourceSessionId's sign, and adjust perEventSourceSessionId to
+ // interpret perEventSourceSessionId's sign, and adjust perEventSourceSessionId to
// represent 0-based positive values
bool bSessionEnable = (commandArgs.perEventSourceSessionId >= 0);
if (commandArgs.perEventSourceSessionId == 0 && commandArgs.enable == false)
// Note that we unconditionally send the manifest whenever we are enabled, even if
// we were already enabled. This is because there may be multiple sessions active
- // and we can't know that all the sessions have seen the manifest.
+ // and we can't know that all the sessions have seen the manifest.
if (!SelfDescribingEvents)
SendManifest(m_rawManifest);
}
// Turn on the enable bit before making the OnEventCommand callback This allows you to do useful
- // things like log messages, or test if keywords are enabled in the callback.
+ // things like log messages, or test if keywords are enabled in the callback.
if (commandArgs.enable)
{
Debug.Assert(m_eventData != null);
// quickly. These are all just optimizations (since later checks will still filter)
// There is a good chance EnabledForAnyListener are not as accurate as
- // they could be, go ahead and get a better estimate.
+ // they could be, go ahead and get a better estimate.
for (int i = 0; i < m_eventData.Length; i++)
{
bool isEnabledForAnyListener = false;
// When the ETW session is created after the EventSource has registered with the ETW system
// we can send any error messages here.
ReportOutOfBandMessage("ERROR: Exception in Command Processing for EventSource " + Name + ": " + e.Message, true);
- // We never throw when doing a command.
+ // We never throw when doing a command.
}
}
/// <summary>
/// If 'value is 'true' then set the eventSource so that 'dispatcher' will receive event with the eventId
/// of 'eventId. If value is 'false' disable the event for that dispatcher. If 'eventId' is out of
- /// range return false, otherwise true.
+ /// range return false, otherwise true.
/// </summary>
internal bool EnableEventForDispatcher(EventDispatcher? dispatcher, EventProviderType eventProviderType, int eventId, bool value)
{
}
/// <summary>
- /// Returns true if any event at all is on.
+ /// Returns true if any event at all is on.
/// </summary>
private bool AnyEventEnabled()
{
m_eventData = eventData;
m_rawManifest = manifest;
}
- // TODO Enforce singleton pattern
+ // TODO Enforce singleton pattern
Debug.Assert(EventListener.s_EventSources != null, "should be called within lock on EventListener.EventListenersLock which ensures s_EventSources to be initialized");
foreach (WeakReference eventSourceRef in EventListener.s_EventSources)
{
}
// Send out the ETW manifest XML out to ETW
- // Today, we only send the manifest to ETW, custom listeners don't get it.
+ // Today, we only send the manifest to ETW, custom listeners don't get it.
private unsafe bool SendManifest(byte[]? rawManifest)
{
bool success = true;
#if FEATURE_MANAGED_ETW
fixed (byte* dataPtr = rawManifest)
{
- // we don't want the manifest to show up in the event log channels so we specify as keywords
+ // we don't want the manifest to show up in the event log channels so we specify as keywords
// everything but the first 8 bits (reserved for the 8 channels)
var manifestDescr = new EventDescriptor(0xFFFE, 1, 0, 0, 0xFE, 0xFFFE, 0x00ffFFFFffffFFFF);
ManifestEnvelope envelope = new ManifestEnvelope();
envelope.Format = ManifestEnvelope.ManifestFormats.SimpleXmlFormat;
envelope.MajorVersion = 1;
envelope.MinorVersion = 0;
- envelope.Magic = 0x5B; // An unusual number that can be checked for consistency.
+ envelope.Magic = 0x5B; // An unusual number that can be checked for consistency.
int dataLeft = rawManifest.Length;
envelope.ChunkNumber = 0;
{
// Turns out that if users set the BufferSize to something less than 64K then WriteEvent
// can fail. If we get this failure on the first chunk try again with something smaller
- // The smallest BufferSize is 1K so if we get to 256 (to account for envelope overhead), we can give up making it smaller.
+ // The smallest BufferSize is 1K so if we get to 256 (to account for envelope overhead), we can give up making it smaller.
if (EventProvider.GetLastWriteEventError() == EventProvider.WriteEventErrorCode.EventTooBig)
{
if (envelope.ChunkNumber == 0 && chunkSize > 256)
#endif
// Helper to deal with the fact that the type we are reflecting over might be loaded in the ReflectionOnly context.
- // When that is the case, we have the build the custom assemblies on a member by hand.
+ // When that is the case, we have the build the custom assemblies on a member by hand.
internal static Attribute? GetCustomAttributeHelper(MemberInfo member, Type attributeType, EventManifestOptions flags = EventManifestOptions.None)
{
#if !ES_BUILD_PN
/// <summary>
/// Evaluates if two related "EventSource"-domain types should be considered the same
/// </summary>
- /// <param name="attributeType">The attribute type in the load context - it's associated with the running
+ /// <param name="attributeType">The attribute type in the load context - it's associated with the running
/// EventSource type. This type may be different fromt he base type of the user-defined EventSource.</param>
/// <param name="reflectedAttributeType">The attribute type in the reflection context - it's associated with
- /// the user-defined EventSource, and is in the same assembly as the eventSourceType passed to
+ /// the user-defined EventSource, and is in the same assembly as the eventSourceType passed to
/// </param>
/// <returns>True - if the types should be considered equivalent, False - otherwise</returns>
private static bool AttributeTypeNamesMatch(Type attributeType, Type reflectedAttributeType)
// Use reflection to look at the attributes of a class, and generate a manifest for it (as UTF8) and
// return the UTF8 bytes. It also sets up the code:EventData structures needed to dispatch events
// at run time. 'source' is the event source to place the descriptors. If it is null,
- // then the descriptors are not creaed, and just the manifest is generated.
+ // then the descriptors are not creaed, and just the manifest is generated.
private static byte[]? CreateManifestAndDescriptors(Type eventSourceType, string? eventSourceDllName, EventSource? source,
EventManifestOptions flags = EventManifestOptions.None)
{
{
MethodInfo[] methods = eventSourceType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
EventAttribute defaultEventAttribute;
- int eventId = 1; // The number given to an event that does not have a explicitly given ID.
+ int eventId = 1; // The number given to an event that does not have a explicitly given ID.
EventMetadata[]? eventData = null;
Dictionary<string, string>? eventsByName = null;
if (source != null || (flags & EventManifestOptions.Strict) != 0)
eventData[0].Name = ""; // Event 0 is the 'write messages string' event, and has an empty name.
}
- // See if we have localization information.
+ // See if we have localization information.
ResourceManager? resources = null;
EventSourceAttribute? eventSourceAttrib = (EventSourceAttribute?)GetCustomAttributeHelper(eventSourceType, typeof(EventSourceAttribute), flags);
if (eventSourceAttrib != null && eventSourceAttrib.LocalizationResources != null)
manifest = new ManifestBuilder(GetName(eventSourceType, flags), GetGuid(eventSourceType), eventSourceDllName,
resources, flags);
- // Add an entry unconditionally for event ID 0 which will be for a string message.
+ // Add an entry unconditionally for event ID 0 which will be for a string message.
manifest.StartEvent("EventSourceMessage", new EventAttribute(0) { Level = EventLevel.LogAlways, Task = (EventTask)0xFFFE });
manifest.AddEventParameter(typeof(string), "message");
manifest.EndEvent();
// Get the EventDescriptor (from the Custom attributes)
EventAttribute? eventAttribute = (EventAttribute?)GetCustomAttributeHelper(method, typeof(EventAttribute), flags);
- // Compat: until v4.5.1 we ignored any non-void returning methods as well as virtual methods for
- // the only reason of limiting the number of methods considered to be events. This broke a common
+ // Compat: until v4.5.1 we ignored any non-void returning methods as well as virtual methods for
+ // the only reason of limiting the number of methods considered to be events. This broke a common
// design of having event sources implement specific interfaces. To fix this in a compatible way
- // we will now allow both non-void returning and virtual methods to be Event methods, as long
+ // we will now allow both non-void returning and virtual methods to be Event methods, as long
// as they are marked with the [Event] attribute
if (/* method.IsVirtual || */ method.IsStatic)
{
continue;
}
- // If we explicitly mark the method as not being an event, then honor that.
+ // If we explicitly mark the method as not being an event, then honor that.
if (GetCustomAttributeHelper(method, typeof(NonEventAttribute), flags) != null)
continue;
eventId++;
string eventName = method.Name;
- if (eventAttribute.Opcode == EventOpcode.Info) // We are still using the default opcode.
+ if (eventAttribute.Opcode == EventOpcode.Info) // We are still using the default opcode.
{
- // By default pick a task ID derived from the EventID, starting with the highest task number and working back
+ // By default pick a task ID derived from the EventID, starting with the highest task number and working back
bool noTask = (eventAttribute.Task == EventTask.None);
if (noTask)
eventAttribute.Task = (EventTask)(0xFFFE - eventAttribute.EventId);
- // Unless we explicitly set the opcode to Info (to override the auto-generate of Start or Stop opcodes,
- // pick a default opcode based on the event name (either Info or start or stop if the name ends with that suffix).
+ // Unless we explicitly set the opcode to Info (to override the auto-generate of Start or Stop opcodes,
+ // pick a default opcode based on the event name (either Info or start or stop if the name ends with that suffix).
if (!eventAttribute.IsOpcodeSet)
eventAttribute.Opcode = GetOpcodeWithDefault(EventOpcode.Info, eventName);
EventMetadata startEventMetadata = eventData[startEventId];
// If you remove the Stop and add a Start does that name match the Start Event's Name?
- // Ideally we would throw an error
+ // Ideally we would throw an error
string taskName = eventName.Substring(0, eventName.Length - s_ActivityStopSuffix.Length); // Remove the Stop suffix to get the task name
if (startEventMetadata.Descriptor.Opcode == (byte)EventOpcode.Start &&
string.Compare(startEventMetadata.Name, 0, taskName, 0, taskName.Length) == 0 &&
noTask = false;
}
}
- if (noTask && (flags & EventManifestOptions.Strict) != 0) // Throw an error if we can compatibly.
+ if (noTask && (flags & EventManifestOptions.Strict) != 0) // Throw an error if we can compatibly.
{
throw new ArgumentException(SR.EventSource_StopsFollowStarts);
}
if (source != null || (flags & EventManifestOptions.Strict) != 0)
{
Debug.Assert(eventData != null);
- // Do checking for user errors (optional, but not a big deal so we do it).
+ // Do checking for user errors (optional, but not a big deal so we do it).
DebugCheckEvent(ref eventsByName, eventData, method, eventAttribute, manifest, flags);
#if FEATURE_MANAGED_ETW_CHANNELS
}
}
- // Tell the TraceLogging stuff where to start allocating its own IDs.
+ // Tell the TraceLogging stuff where to start allocating its own IDs.
NameInfo.ReserveEventIDsBelow(eventId);
if (source != null)
{
Debug.Assert(eventData != null);
TrimEventDescriptors(ref eventData);
- source.m_eventData = eventData; // officially initialize it. We do this at most once (it is racy otherwise).
+ source.m_eventData = eventData; // officially initialize it. We do this at most once (it is racy otherwise).
#if FEATURE_MANAGED_ETW_CHANNELS
source.m_channelData = manifest.GetChannelData();
#endif
private static bool RemoveFirstArgIfRelatedActivityId(ref ParameterInfo[] args)
{
- // If the first parameter is (case insensitive) 'relatedActivityId' then skip it.
+ // If the first parameter is (case insensitive) 'relatedActivityId' then skip it.
if (args.Length > 0 && args[0].ParameterType == typeof(Guid) &&
string.Equals(args[0].Name, "relatedActivityId", StringComparison.OrdinalIgnoreCase))
{
}
// adds a enumeration (keyword, opcode, task or channel) represented by 'staticField'
- // to the manifest.
+ // to the manifest.
private static void AddProviderEnumKind(ManifestBuilder manifest, FieldInfo staticField, string providerEnumKind)
{
bool reflectionOnly = staticField.Module.Assembly.ReflectionOnly();
}
// Helper used by code:CreateManifestAndDescriptors that trims the m_eventData array to the correct
- // size after all event descriptors have been added.
+ // size after all event descriptors have been added.
private static void TrimEventDescriptors(ref EventMetadata[] eventData)
{
int idx = eventData.Length;
if (eventData[idx].Descriptor.EventId != 0)
break;
}
- if (eventData.Length - idx > 2) // allow one wasted slot.
+ if (eventData.Length - idx > 2) // allow one wasted slot.
{
EventMetadata[] newValues = new EventMetadata[idx + 1];
Array.Copy(eventData, 0, newValues, 0, newValues.Length);
}
// Helper used by code:CreateManifestAndDescriptors to find user mistakes like reusing an event
- // index for two distinct events etc. Throws exceptions when it finds something wrong.
+ // index for two distinct events etc. Throws exceptions when it finds something wrong.
private static void DebugCheckEvent(ref Dictionary<string, string>? eventsByName,
EventMetadata[] eventData, MethodInfo method, EventAttribute eventAttribute,
ManifestBuilder manifest, EventManifestOptions options)
manifest.ManifestError(SR.Format(SR.EventSource_EventIdReused, evtName, evtId, eventData[evtId].Name), true);
}
- // We give a task to things if they don't have one.
- // TODO this is moderately expensive (N*N). We probably should not even bother....
+ // We give a task to things if they don't have one.
+ // TODO this is moderately expensive (N*N). We probably should not even bother....
Debug.Assert(eventAttribute.Task != EventTask.None || eventAttribute.Opcode != EventOpcode.Info);
for (int idx = 0; idx < eventData.Length; ++idx)
{
- // skip unused Event IDs.
+ // skip unused Event IDs.
if (eventData[idx].Name == null)
continue;
{
manifest.ManifestError(SR.Format(SR.EventSource_TaskOpcodePairReused,
evtName, evtId, eventData[idx].Name, idx));
- // If we are not strict stop on first error. We have had problems with really large providers taking forever. because of many errors.
+ // If we are not strict stop on first error. We have had problems with really large providers taking forever. because of many errors.
if ((options & EventManifestOptions.Strict) == 0)
break;
}
failure = true;
else
{
- // If you have the auto-assigned Task, then you did not explicitly set one.
+ // If you have the auto-assigned Task, then you did not explicitly set one.
// This is OK for Start events because we have special logic to assign the task to a prefix derived from the event name
- // But all other cases we want to catch the omission.
+ // But all other cases we want to catch the omission.
var autoAssignedTask = (EventTask)(0xFFFE - evtId);
if ((eventAttribute.Opcode != EventOpcode.Start && eventAttribute.Opcode != EventOpcode.Stop) && eventAttribute.Task == autoAssignedTask)
failure = true;
/// <summary>
/// This method looks at the IL and tries to pattern match against the standard
- /// 'boilerplate' event body
+ /// 'boilerplate' event body
/// <code>
- /// { if (Enabled()) WriteEvent(#, ...) }
+ /// { if (Enabled()) WriteEvent(#, ...) }
/// </code>
/// If the pattern matches, it returns the literal number passed as the first parameter to
/// the WriteEvent. This is used to find common user errors (mismatching this
- /// number with the EventAttribute ID). It is only used for validation.
+ /// number with the EventAttribute ID). It is only used for validation.
/// </summary>
/// <param name="method">The method to probe.</param>
/// <returns>The literal value or -1 if the value could not be determined. </returns>
{
#if (!ES_BUILD_PCL && !ES_BUILD_PN)
// Currently searches for the following pattern
- //
+ //
// ... // CAN ONLY BE THE INSTRUCTIONS BELOW
// LDARG0
// LDC.I4 XXX
// ... // CAN ONLY BE THE INSTRUCTIONS BELOW CAN'T BE A BRANCH OR A CALL
- // CALL
+ // CALL
// NOP // 0 or more times
// RET
- //
- // If we find this pattern we return the XXX. Otherwise we return -1.
+ //
+ // If we find this pattern we return the XXX. Otherwise we return -1.
#if ES_BUILD_STANDALONE
(new ReflectionPermission(ReflectionPermissionFlag.MemberAccess)).Assert();
#endif
if (retVal >= 0)
{
- // Is this call just before return?
+ // Is this call just before return?
for (int search = idx + 1; search < instrs.Length; search++)
{
if (instrs[search] == 42) // RET
}
/// <summary>
- /// Sends an error message to the debugger (outputDebugString), as well as the EventListeners
- /// It will do this even if the EventSource is not enabled.
- /// TODO remove flush parameter it is not used.
+ /// Sends an error message to the debugger (outputDebugString), as well as the EventListeners
+ /// It will do this even if the EventSource is not enabled.
+ /// TODO remove flush parameter it is not used.
/// </summary>
[SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
internal void ReportOutOfBandMessage(string msg, bool flush)
{
if (m_outOfBandMessageCount == 16)
return;
- m_outOfBandMessageCount = 16; // Mark that we hit the limit. Notify them that this is the case.
+ m_outOfBandMessageCount = 16; // Mark that we hit the limit. Notify them that this is the case.
msg = "Reached message limit. End of EventSource error messages.";
}
throw new ArgumentException(SR.EventSource_InvalidEventFormat, nameof(settings));
}
- // If you did not explicitly ask for manifest, you get self-describing.
+ // If you did not explicitly ask for manifest, you get self-describing.
if ((settings & evtFormatMask) == 0)
settings |= EventSourceSettings.EtwSelfDescribingEventFormat;
return settings;
}
}
- // private instance state
+ // private instance state
private string m_name = null!; // My friendly name (privided in ctor)
- internal int m_id; // A small integer that is unique to this instance.
- private Guid m_guid; // GUID representing the ETW eventSource to the OS.
+ internal int m_id; // A small integer that is unique to this instance.
+ private Guid m_guid; // GUID representing the ETW eventSource to the OS.
internal volatile EventMetadata[]? m_eventData; // None per-event data
private volatile byte[]? m_rawManifest; // Bytes to send out representing the event schema
internal EventLevel m_level; // highest level enabled by any output dispatcher
internal EventKeywords m_matchAnyKeyword; // the logical OR of all levels enabled by any output dispatcher (zero is a special case) meaning 'all keywords'
- // Dispatching state
+ // Dispatching state
internal volatile EventDispatcher? m_Dispatchers; // Linked list of code:EventDispatchers we write the data to (we also do ETW specially)
#if FEATURE_MANAGED_ETW
private volatile OverideEventProvider m_etwProvider = null!; // This hooks up ETW commands to our 'OnEventCommand' callback
#if FEATURE_PERFTRACING
private volatile OverideEventProvider m_eventPipeProvider = null!;
#endif
- private bool m_completelyInited; // The EventSource constructor has returned without exception.
- private Exception? m_constructionException; // If there was an exception construction, this is it
+ private bool m_completelyInited; // The EventSource constructor has returned without exception.
+ private Exception? m_constructionException; // If there was an exception construction, this is it
private byte m_outOfBandMessageCount; // The number of out of band messages sent (we throttle them
- private EventCommandEventArgs? m_deferredCommands;// If we get commands before we are fully we store them here and run the when we are fully inited.
+ private EventCommandEventArgs? m_deferredCommands;// If we get commands before we are fully we store them here and run the when we are fully inited.
private string[]? m_traits; // Used to implement GetTraits
/// </summary>
Default = 0,
/// <summary>
- /// Normally an EventSource NEVER throws; setting this option will tell it to throw when it encounters errors.
+ /// Normally an EventSource NEVER throws; setting this option will tell it to throw when it encounters errors.
/// </summary>
ThrowOnEventWriteErrors = 1,
/// <summary>
/// Setting this option is a directive to the ETW listener should use manifest-based format when
- /// firing events. This is the default option when defining a type derived from EventSource
+ /// firing events. This is the default option when defining a type derived from EventSource
/// (using the protected EventSource constructors).
/// Only one of EtwManifestEventFormat or EtwSelfDescribingEventFormat should be specified
/// </summary>
/// <summary>
/// Setting this option is a directive to the ETW listener should use self-describing event format
/// when firing events. This is the default option when creating a new instance of the EventSource
- /// type (using the public EventSource constructors).
+ /// type (using the public EventSource constructors).
/// Only one of EtwManifestEventFormat or EtwSelfDescribingEventFormat should be specified
/// </summary>
EtwSelfDescribingEventFormat = 8,
/// longer needed.
/// <para>
/// Once created, EventListeners can enable or disable on a per-eventSource basis using verbosity levels
- /// (<see cref="EventLevel"/>) and bitfields (<see cref="EventKeywords"/>) to further restrict the set of
- /// events to be sent to the dispatcher. The dispatcher can also send arbitrary commands to a particular
+ /// (<see cref="EventLevel"/>) and bitfields (<see cref="EventKeywords"/>) to further restrict the set of
+ /// events to be sent to the dispatcher. The dispatcher can also send arbitrary commands to a particular
/// eventSource using the 'SendCommand' method. The meaning of the commands are eventSource specific.
/// </para><para>
/// The Null Guid (that is (new Guid()) has special meaning as a wildcard for 'all current eventSources in
/// This can happen for all existing EventSources when the EventListener is created
/// as well as for any EventSources that come into existence after the EventListener
/// has been created.
- ///
+ ///
/// These 'catch up' events are called during the construction of the EventListener.
/// Subclasses need to be prepared for that.
- ///
- /// In a multi-threaded environment, it is possible that 'EventSourceEventWrittenCallback'
+ ///
+ /// In a multi-threaded environment, it is possible that 'EventSourceEventWrittenCallback'
/// events for a particular eventSource to occur BEFORE the EventSourceCreatedCallback is issued.
/// </summary>
public event EventHandler<EventSourceCreatedEventArgs>? EventSourceCreated
}
/// <summary>
- /// This event is raised whenever an event has been written by a EventSource for which
- /// the EventListener has enabled events.
+ /// This event is raised whenever an event has been written by a EventSource for which
+ /// the EventListener has enabled events.
/// </summary>
public event EventHandler<EventWrittenEventArgs>? EventWritten;
/// <summary>
/// Create a new EventListener in which all events start off turned off (use EnableEvents to turn
- /// them on).
+ /// them on).
/// </summary>
public EventListener()
{
- // This will cause the OnEventSourceCreated callback to fire.
+ // This will cause the OnEventSourceCreated callback to fire.
CallBackForExistingEventSources(true, (obj, args) =>
{
args.EventSource!.AddListener((EventListener)obj!);
}
else
{
- // Find 'this' from the s_Listeners linked list.
+ // Find 'this' from the s_Listeners linked list.
EventListener prev = s_Listeners;
for (;;)
{
if (cur == this)
{
// Found our Listener, remove references to it in the eventSources
- prev.m_Next = cur.m_Next; // Remove entry.
+ prev.m_Next = cur.m_Next; // Remove entry.
RemoveReferencesToListenerInEventSources(cur);
break;
}
// 'cleanup' associated with this object
/// <summary>
- /// Enable all events from the eventSource identified by 'eventSource' to the current
+ /// Enable all events from the eventSource identified by 'eventSource' to the current
/// dispatcher that have a verbosity level of 'level' or lower.
- ///
- /// This call can have the effect of REDUCING the number of events sent to the
+ ///
+ /// This call can have the effect of REDUCING the number of events sent to the
/// dispatcher if 'level' indicates a less verbose level than was previously enabled.
- ///
+ ///
/// This call never has an effect on other EventListeners.
///
/// </summary>
/// Enable all events from the eventSource identified by 'eventSource' to the current
/// dispatcher that have a verbosity level of 'level' or lower and have a event keyword
/// matching any of the bits in 'matchAnyKeyword'.
- ///
- /// This call can have the effect of REDUCING the number of events sent to the
+ ///
+ /// This call can have the effect of REDUCING the number of events sent to the
/// dispatcher if 'level' indicates a less verbose level than was previously enabled or
/// if 'matchAnyKeyword' has fewer keywords set than where previously set.
- ///
+ ///
/// This call never has an effect on other EventListeners.
/// </summary>
public void EnableEvents(EventSource eventSource, EventLevel level, EventKeywords matchAnyKeyword)
/// Enable all events from the eventSource identified by 'eventSource' to the current
/// dispatcher that have a verbosity level of 'level' or lower and have a event keyword
/// matching any of the bits in 'matchAnyKeyword' as well as any (eventSource specific)
- /// effect passing additional 'key-value' arguments 'arguments' might have.
- ///
- /// This call can have the effect of REDUCING the number of events sent to the
+ /// effect passing additional 'key-value' arguments 'arguments' might have.
+ ///
+ /// This call can have the effect of REDUCING the number of events sent to the
/// dispatcher if 'level' indicates a less verbose level than was previously enabled or
/// if 'matchAnyKeyword' has fewer keywords set than where previously set.
- ///
+ ///
/// This call never has an effect on other EventListeners.
- /// </summary>
+ /// </summary>
public void EnableEvents(EventSource eventSource, EventLevel level, EventKeywords matchAnyKeyword, IDictionary<string, string?>? arguments)
{
if (eventSource == null)
#endif // FEATURE_PERFTRACING
}
/// <summary>
- /// Disables all events coming from eventSource identified by 'eventSource'.
- ///
- /// This call never has an effect on other EventListeners.
+ /// Disables all events coming from eventSource identified by 'eventSource'.
+ ///
+ /// This call never has an effect on other EventListeners.
/// </summary>
public void DisableEvents(EventSource eventSource)
{
/// This can happen for all existing EventSources when the EventListener is created
/// as well as for any EventSources that come into existence after the EventListener
/// has been created.
- ///
+ ///
/// These 'catch up' events are called during the construction of the EventListener.
/// Subclasses need to be prepared for that.
- ///
+ ///
/// In a multi-threaded environment, it is possible that 'OnEventWritten' callbacks
/// for a particular eventSource to occur BEFORE the OnEventSourceCreated is issued.
/// </summary>
}
/// <summary>
- /// This method is called whenever an event has been written by a EventSource for which
- /// the EventListener has enabled events.
+ /// This method is called whenever an event has been written by a EventSource for which
+ /// the EventListener has enabled events.
/// </summary>
/// <param name="eventData"></param>
protected internal virtual void OnEventWritten(EventWrittenEventArgs eventData)
/// <summary>
/// This routine adds newEventSource to the global list of eventSources, it also assigns the
/// ID to the eventSource (which is simply the ordinal in the global list).
- ///
+ ///
/// EventSources currently do not pro-actively remove themselves from this list. Instead
/// when eventSources's are GCed, the weak handle in this list naturally gets nulled, and
/// we will reuse the slot. Today this list never shrinks (but we do reuse entries
// Periodically search the list for existing entries to reuse, this avoids
- // unbounded memory use if we keep recycling eventSources (an unlikely thing).
+ // unbounded memory use if we keep recycling eventSources (an unlikely thing).
int newIndex = -1;
if (s_EventSources.Count % 64 == 63) // on every block of 64, fill up the block before continuing
{
- int i = s_EventSources.Count; // Work from the top down.
+ int i = s_EventSources.Count; // Work from the top down.
while (0 < i)
{
--i;
// Whenver we have async callbacks from native code, there is an ugly issue where
// during .NET shutdown native code could be calling the callback, but the CLR
- // has already prohibited callbacks to managed code in the appdomain, causing the CLR
+ // has already prohibited callbacks to managed code in the appdomain, causing the CLR
// to throw a COMPLUS_BOOT_EXCEPTION. The guideline we give is that you must unregister
- // such callbacks on process shutdown or appdomain so that unmanaged code will never
- // do this. This is what this callback is for.
+ // such callbacks on process shutdown or appdomain so that unmanaged code will never
+ // do this. This is what this callback is for.
// See bug 724140 for more
private static void DisposeOnShutdown(object? sender, EventArgs e)
{
/// <summary>
/// Helper used in code:Dispose that removes any references to 'listenerToRemove' in any of the
- /// eventSources in the appdomain.
- ///
- /// The EventListenersLock must be held before calling this routine.
+ /// eventSources in the appdomain.
+ ///
+ /// The EventListenersLock must be held before calling this routine.
/// </summary>
private static void RemoveReferencesToListenerInEventSources(EventListener listenerToRemove)
{
eventSource.m_Dispatchers = eventSource.m_Dispatchers.m_Next;
else
{
- // Remove 'listenerToRemove' from the eventSource.m_Dispatchers linked list.
+ // Remove 'listenerToRemove' from the eventSource.m_Dispatchers linked list.
EventDispatcher? prev = eventSource.m_Dispatchers;
for (;;)
{
}
if (cur.m_Listener == listenerToRemove)
{
- prev.m_Next = cur.m_Next; // Remove entry.
+ prev.m_Next = cur.m_Next; // Remove entry.
break;
}
prev = cur;
}
/// <summary>
- /// Checks internal consistency of EventSources/Listeners.
+ /// Checks internal consistency of EventSources/Listeners.
/// </summary>
[Conditional("DEBUG")]
internal static void Validate()
lock (EventListenersLock)
{
Debug.Assert(s_EventSources != null);
- // Get all listeners
+ // Get all listeners
Dictionary<EventListener, bool> allListeners = new Dictionary<EventListener, bool>();
EventListener? cur = s_Listeners;
while (cur != null)
cur = cur.m_Next;
}
- // For all eventSources
+ // For all eventSources
int id = -1;
foreach (WeakReference eventSourceRef in s_EventSources)
{
continue;
Debug.Assert(eventSource.m_id == id, "Unexpected event source ID.");
- // None listeners on eventSources exist in the dispatcher list.
+ // None listeners on eventSources exist in the dispatcher list.
EventDispatcher? dispatcher = eventSource.m_Dispatchers;
while (dispatcher != null)
{
dispatcher = dispatcher.m_Next;
}
- // Every dispatcher is on Dispatcher List of every eventSource.
+ // Every dispatcher is on Dispatcher List of every eventSource.
foreach (EventListener listener in allListeners.Keys)
{
dispatcher = eventSource.m_Dispatchers;
{
Debug.Assert(s_EventSources != null);
- // Disallow creating EventListener reentrancy.
+ // Disallow creating EventListener reentrancy.
if (s_CreatingListener)
{
throw new InvalidOperationException(SR.EventSource_ListenerCreatedInsideCallback);
if (addToListenersList)
{
- // Add to list of listeners in the system, do this BEFORE firing the 'OnEventSourceCreated' so that
+ // Add to list of listeners in the system, do this BEFORE firing the 'OnEventSourceCreated' so that
// Those added sources see this listener.
this.m_Next = s_Listeners;
s_Listeners = this;
if (callback != null)
{
// Find all existing eventSources call OnEventSourceCreated to 'catchup'
- // Note that we DO have reentrancy here because 'AddListener' calls out to user code (via OnEventSourceCreated callback)
+ // Note that we DO have reentrancy here because 'AddListener' calls out to user code (via OnEventSourceCreated callback)
// We tolerate this by iterating over a copy of the list here. New event sources will take care of adding listeners themselves
// EventSources are not guaranteed to be added at the end of the s_EventSource list -- We re-use slots when a new source
// is created.
// static fields
/// <summary>
- /// The list of all listeners in the appdomain. Listeners must be explicitly disposed to remove themselves
- /// from this list. Note that EventSources point to their listener but NOT the reverse.
+ /// The list of all listeners in the appdomain. Listeners must be explicitly disposed to remove themselves
+ /// from this list. Note that EventSources point to their listener but NOT the reverse.
/// </summary>
internal static EventListener? s_Listeners;
/// <summary>
- /// The list of all active eventSources in the appdomain. Note that eventSources do NOT
+ /// The list of all active eventSources in the appdomain. Note that eventSources do NOT
/// remove themselves from this list this is a weak list and the GC that removes them may
- /// not have happened yet. Thus it can contain event sources that are dead (thus you have
- /// to filter those out.
+ /// not have happened yet. Thus it can contain event sources that are dead (thus you have
+ /// to filter those out.
/// </summary>
internal static List<WeakReference>? s_EventSources;
/// <summary>
- /// Used to disallow reentrancy.
+ /// Used to disallow reentrancy.
/// </summary>
private static bool s_CreatingListener = false;
internal EventDispatcher? dispatcher;
internal EventProviderType eventProviderType;
- // These are the arguments of sendCommand and are only used for deferring commands until after we are fully initialized.
+ // These are the arguments of sendCommand and are only used for deferring commands until after we are fully initialized.
internal EventListener? listener;
internal int perEventSourceSessionId;
internal int etwSessionId;
internal bool enable;
internal EventLevel level;
internal EventKeywords matchAnyKeyword;
- internal EventCommandEventArgs? nextCommand; // We form a linked list of these deferred commands.
+ internal EventCommandEventArgs? nextCommand; // We form a linked list of these deferred commands.
#endregion
}
public class EventWrittenEventArgs : EventArgs
{
/// <summary>
- /// The name of the event.
+ /// The name of the event.
/// </summary>
public string? EventName
{
}
/// <summary>
- /// Any provider/user defined options associated with the event.
+ /// Any provider/user defined options associated with the event.
/// </summary>
public EventTags Tags
{
}
/// <summary>
- /// Gets the message for the event. If the message has {N} parameters they are NOT substituted.
+ /// Gets the message for the event. If the message has {N} parameters they are NOT substituted.
/// </summary>
public string? Message
{
}
/// <summary>
- /// Allows customizing defaults and specifying localization support for the event source class to which it is applied.
+ /// Allows customizing defaults and specifying localization support for the event source class to which it is applied.
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public sealed class EventSourceAttribute : Attribute
public string? Name { get; set; }
/// <summary>
- /// Overrides the default (calculated) Guid of an EventSource type. Explicitly defining a GUID is discouraged,
+ /// Overrides the default (calculated) Guid of an EventSource type. Explicitly defining a GUID is discouraged,
/// except when upgrading existing ETW providers to using event sources.
/// </summary>
public string? Guid { get; set; }
/// <summary>
/// <para>
- /// EventSources support localization of events. The names used for events, opcodes, tasks, keywords and maps
- /// can be localized to several languages if desired. This works by creating a ResX style string table
- /// (by simply adding a 'Resource File' to your project). This resource file is given a name e.g.
- /// 'DefaultNameSpace.ResourceFileName' which can be passed to the ResourceManager constructor to read the
- /// resources. This name is the value of the LocalizationResources property.
+ /// EventSources support localization of events. The names used for events, opcodes, tasks, keywords and maps
+ /// can be localized to several languages if desired. This works by creating a ResX style string table
+ /// (by simply adding a 'Resource File' to your project). This resource file is given a name e.g.
+ /// 'DefaultNameSpace.ResourceFileName' which can be passed to the ResourceManager constructor to read the
+ /// resources. This name is the value of the LocalizationResources property.
/// </para><para>
- /// If LocalizationResources property is non-null, then EventSource will look up the localized strings for events by
+ /// If LocalizationResources property is non-null, then EventSource will look up the localized strings for events by
/// using the following resource naming scheme
/// </para>
/// <para>* event_EVENTNAME</para>
/// <para>* keyword_KEYWORDNAME</para>
/// <para>* map_MAPNAME</para>
/// <para>
- /// where the capitalized name is the name of the event, task, keyword, or map value that should be localized.
- /// Note that the localized string for an event corresponds to the Message string, and can have {0} values
- /// which represent the payload values.
+ /// where the capitalized name is the name of the event, task, keyword, or map value that should be localized.
+ /// Note that the localized string for an event corresponds to the Message string, and can have {0} values
+ /// which represent the payload values.
/// </para>
/// </summary>
public string? LocalizationResources { get; set; }
public byte Version { get; set; }
/// <summary>
- /// This can be specified to enable formatting and localization of the event's payload. You can
- /// use standard .NET substitution operators (eg {1}) in the string and they will be replaced
- /// with the 'ToString()' of the corresponding part of the event payload.
+ /// This can be specified to enable formatting and localization of the event's payload. You can
+ /// use standard .NET substitution operators (eg {1}) in the string and they will be replaced
+ /// with the 'ToString()' of the corresponding part of the event payload.
/// </summary>
public string? Message { get; set; }
/// <summary>
/// User defined options associated with the event. These do not have meaning to the EventSource but
- /// are passed through to listeners which given them semantics.
+ /// are passed through to listeners which given them semantics.
/// </summary>
public EventTags Tags { get; set; }
/// {
/// [Channel(Enabled = true, EventChannelType = EventChannelType.Admin)]
/// public const EventChannel Admin = (EventChannel)16;
- ///
+ ///
/// [Channel(Enabled = false, EventChannelType = EventChannelType.Operational)]
/// public const EventChannel Operational = (EventChannel)17;
/// }
/// </summary>
[AttributeUsage(AttributeTargets.Field)]
#if FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
- public
+ public
#endif
class EventChannelAttribute : Attribute
{
/// Specifies an SDDL access descriptor that controls access to the log file that backs the channel.
/// See MSDN (https://docs.microsoft.com/en-us/windows/desktop/WES/eventmanifestschema-channeltype-complextype) for details.
/// </summary>
- public string? Access { get; set; }
+ public string? Access { get; set; }
/// <summary>
/// Allows importing channels defined in external manifests
/// Allowed channel types
/// </summary>
#if FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
- public
+ public
#endif
enum EventChannelType
{
#if FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
/// <summary>
- /// Allowed isolation levels. See MSDN (https://docs.microsoft.com/en-us/windows/desktop/WES/eventmanifestschema-channeltype-complextype)
- /// for the default permissions associated with each level. EventChannelIsolation and Access allows control over the
+ /// Allowed isolation levels. See MSDN (https://docs.microsoft.com/en-us/windows/desktop/WES/eventmanifestschema-channeltype-complextype)
+ /// for the default permissions associated with each level. EventChannelIsolation and Access allows control over the
/// access permissions for the channel and backing file.
/// </summary>
- public
+ public
enum EventChannelIsolation
{
/// <summary>
/// <summary>
/// code:EventDispatchers are a simple 'helper' structure that holds the filtering state
/// (m_EventEnabled) for a particular EventSource X EventListener tuple
- ///
- /// Thus a single EventListener may have many EventDispatchers (one for every EventSource
+ ///
+ /// Thus a single EventListener may have many EventDispatchers (one for every EventSource
/// that EventListener has activate) and a Single EventSource may also have many
- /// event Dispatchers (one for every EventListener that has activated it).
- ///
- /// Logically a particular EventDispatcher belongs to exactly one EventSource and exactly
+ /// event Dispatchers (one for every EventListener that has activated it).
+ ///
+ /// Logically a particular EventDispatcher belongs to exactly one EventSource and exactly
/// one EventListener (although EventDispatcher does not 'remember' the EventSource it is
- /// associated with.
+ /// associated with.
/// </summary>
internal class EventDispatcher
{
// Only guaranteed to exist after a InsureInit()
internal EventDispatcher? m_Next; // These form a linked list in code:EventSource.m_Dispatchers
- // Of all listeners for that eventSource.
+ // Of all listeners for that eventSource.
}
/// <summary>
/// <summary>
/// ManifestBuilder is designed to isolate the details of the message of the event from the
- /// rest of EventSource. This one happens to create XML.
+ /// rest of EventSource. This one happens to create XML.
/// </summary>
internal class ManifestBuilder
{
/// <summary>
/// Build a manifest for 'providerName' with the given GUID, which will be packaged into 'dllName'.
- /// 'resources, is a resource manager. If specified all messages are localized using that manager.
+ /// 'resources, is a resource manager. If specified all messages are localized using that manager.
/// </summary>
public ManifestBuilder(string providerName, Guid providerGuid, string? dllName, ResourceManager? resources,
EventManifestOptions flags)
Append(" level=\"").Append(GetLevelName(eventAttribute.Level)).Append("\"").
Append(" symbol=\"").Append(eventName).Append("\"");
- // at this point we add to the manifest's stringTab a message that is as-of-yet
- // "untranslated to manifest convention", b/c we don't have the number or position
+ // at this point we add to the manifest's stringTab a message that is as-of-yet
+ // "untranslated to manifest convention", b/c we don't have the number or position
// of any byte[] args (which require string format index updates)
WriteMessageAttrib(events, "event", eventName, eventAttribute.Message);
if (mapsTab == null)
mapsTab = new Dictionary<string, Type>();
if (!mapsTab.ContainsKey(type.Name))
- mapsTab.Add(type.Name, type); // Remember that we need to dump the type enumeration
+ mapsTab.Add(type.Name, type); // Remember that we need to dump the type enumeration
}
templates.Append("/>").AppendLine();
#if FEATURE_MANAGED_ETW_CHANNELS
// Channel keywords are generated one per channel to allow channel based filtering in event viewer. These keywords are autogenerated
// by mc.exe for compiling a manifest and are based on the order of the channels (fields) in the Channels inner class (when advanced
- // channel support is enabled), or based on the order the predefined channels appear in the EventAttribute properties (for simple
+ // channel support is enabled), or based on the order the predefined channels appear in the EventAttribute properties (for simple
// support). The manifest generated *MUST* have the channels specified in the same order (that's how our computed keywords are mapped
// to channels by the OS infrastructure).
- // If channelKeyworkds is present, and has keywords bits in the ValidPredefinedChannelKeywords then it is
- // assumed that the keyword for that channel should be that bit.
- // otherwise we allocate a channel bit for the channel.
- // explicit channel bits are only used by WCF to mimic an existing manifest,
- // so we don't dont do error checking.
+ // If channelKeyworkds is present, and has keywords bits in the ValidPredefinedChannelKeywords then it is
+ // assumed that the keyword for that channel should be that bit.
+ // otherwise we allocate a channel bit for the channel.
+ // explicit channel bits are only used by WCF to mimic an existing manifest,
+ // so we don't dont do error checking.
public ulong GetChannelKeyword(EventChannel channel, ulong channelKeyword = 0)
{
- // strip off any non-channel keywords, since we are only interested in channels here.
+ // strip off any non-channel keywords, since we are only interested in channels here.
channelKeyword &= ValidPredefinedChannelKeywords;
if (channelTab == null)
{
ChannelInfo? info;
if (!channelTab.TryGetValue((int)channel, out info))
{
- // If we were not given an explicit channel, allocate one.
+ // If we were not given an explicit channel, allocate one.
if (channelKeyword != 0)
{
channelKeyword = nextChannelKeywordBit;
string mapKind = isbitmap ? "bitMap" : "valueMap";
sb.Append(" <").Append(mapKind).Append(" name=\"").Append(enumType.Name).Append("\">").AppendLine();
- // write out each enum value
+ // write out each enum value
FieldInfo[] staticFields = enumType.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static);
bool anyValuesWritten = false;
foreach (FieldInfo staticField in staticFields)
{
ulong hexValue;
if (constantValObj is ulong)
- hexValue = (ulong)constantValObj; // This is the only integer type that can't be represented by a long.
- else
- hexValue = (ulong) Convert.ToInt64(constantValObj); // Handles all integer types except ulong.
+ hexValue = (ulong)constantValObj; // This is the only integer type that can't be represented by a long.
+ else
+ hexValue = (ulong) Convert.ToInt64(constantValObj); // Handles all integer types except ulong.
- // ETW requires all bitmap values to be powers of 2. Skip the ones that are not.
- // TODO: Warn people about the dropping of values.
+ // ETW requires all bitmap values to be powers of 2. Skip the ones that are not.
+ // TODO: Warn people about the dropping of values.
if (isbitmap && ((hexValue & (hexValue - 1)) != 0 || hexValue == 0))
continue;
sb.Append(" <map value=\"0x").Append(hexValue.ToString("x", CultureInfo.InvariantCulture)).Append("\"");
}
// the OS requires that bitmaps and valuemaps have at least one value or it reject the whole manifest.
- // To avoid that put a 'None' entry if there are no other values.
+ // To avoid that put a 'None' entry if there are no other values.
if (!anyValuesWritten)
{
sb.Append(" <map value=\"0x0\"");
}
else
{
- // Work around a cornercase ETW issue where a manifest with no templates causes
+ // Work around a cornercase ETW issue where a manifest with no templates causes
// ETW events to not get sent to their associated channel.
sb.Append(" <template tid=\"_empty\"></template>").AppendLine();
}
sb.Append("</events>").AppendLine();
sb.Append("</instrumentation>").AppendLine();
- // Output the localization information.
+ // Output the localization information.
sb.Append("<localization>").AppendLine();
List<CultureInfo>? cultures = null;
private void WriteMessageAttrib(StringBuilder stringBuilder, string elementName, string name, string? value)
{
string key = elementName + "_" + name;
- // See if the user wants things localized.
+ // See if the user wants things localized.
if (resources != null)
{
// resource fallback: strings in the neutral culture will take precedence over inline strings
/// <summary>
/// There's no API to enumerate all languages an assembly is localized into, so instead
- /// we enumerate through all the "known" cultures and attempt to load a corresponding satellite
+ /// we enumerate through all the "known" cultures and attempt to load a corresponding satellite
/// assembly
/// </summary>
/// <param name="resources"></param>
ManifestError(SR.Format(SR.EventSource_UndefinedChannel, channel, eventName));
// allow channels to be auto-defined. The well known ones get their well known names, and the
- // rest get names Channel<N>. This allows users to modify the Manifest if they want more advanced features.
+ // rest get names Channel<N>. This allows users to modify the Manifest if they want more advanced features.
if (channelTab == null)
channelTab = new Dictionary<int, ChannelInfo>(4);
- string channelName = channel.ToString(); // For well know channels this is a nice name, otherwise a number
+ string channelName = channel.ToString(); // For well know channels this is a nice name, otherwise a number
if (EventChannel.Debug < channel)
- channelName = "Channel" + channelName; // Add a 'Channel' prefix for numbers.
+ channelName = "Channel" + channelName; // Add a 'Channel' prefix for numbers.
AddChannel(channelName, (int)channel, GetDefaultChannelAttribute(channel));
if (!channelTab.TryGetValue((int)channel, out info))
{
#if FEATURE_MANAGED_ETW_CHANNELS
// ignore keywords associate with channels
- // See ValidPredefinedChannelKeywords def for more.
+ // See ValidPredefinedChannelKeywords def for more.
keywords &= ~ValidPredefinedChannelKeywords;
#endif
{
FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
var typeName = GetTypeName(fields[0].FieldType);
- return typeName.Replace("win:Int", "win:UInt"); // ETW requires enums to be unsigned.
+ return typeName.Replace("win:Int", "win:UInt"); // ETW requires enums to be unsigned.
}
switch (type.GetTypeCode())
private static readonly string[] s_escapes = { "&", "<", ">", "'", """, "%r", "%n", "%t" };
// Manifest messages use %N conventions for their message substitutions. Translate from
- // .NET conventions. We can't use RegEx for this (we are in mscorlib), so we do it 'by hand'
+ // .NET conventions. We can't use RegEx for this (we are in mscorlib), so we do it 'by hand'
private string TranslateToManifestConvention(string eventMessage, string evtName)
{
- StringBuilder? stringBuilder = null; // We lazily create this
+ StringBuilder? stringBuilder = null; // We lazily create this
int writtenSoFar = 0;
int chIdx = -1;
for (int i = 0; ;)
int manIndex = TranslateIndexToManifestConvention(argNum, evtName);
stringBuilder.Append('%').Append(manIndex);
// An '!' after the insert specifier {n} will be interpreted as a literal.
- // We'll escape it so that mc.exe does not attempt to consider it the
+ // We'll escape it so that mc.exe does not attempt to consider it the
// beginning of a format string.
if (i < eventMessage.Length && eventMessage[i] == '!')
{
Dictionary<ulong, string>? keywordTab;
Dictionary<string, Type>? mapsTab;
- Dictionary<string, string> stringTab; // Maps unlocalized strings to localized ones
+ Dictionary<string, string> stringTab; // Maps unlocalized strings to localized ones
#if FEATURE_MANAGED_ETW_CHANNELS
// WCF used EventSource to mimic a existing ETW manifest. To support this
- // in just their case, we allowed them to specify the keywords associated
- // with their channels explicitly. ValidPredefinedChannelKeywords is
+ // in just their case, we allowed them to specify the keywords associated
+ // with their channels explicitly. ValidPredefinedChannelKeywords is
// this set of channel keywords that we allow to be explicitly set. You
- // can ignore these bits otherwise.
+ // can ignore these bits otherwise.
internal const ulong ValidPredefinedChannelKeywords = 0xF000000000000000;
ulong nextChannelKeywordBit = 0x8000000000000000; // available Keyword bit to be used for next channel definition, grows down
const int MaxCountChannels = 8; // a manifest can defined at most 8 ETW channels
#endif
- StringBuilder sb; // Holds the provider information.
- StringBuilder events; // Holds the events.
+ StringBuilder sb; // Holds the provider information.
+ StringBuilder events; // Holds the events.
StringBuilder templates;
#if FEATURE_MANAGED_ETW_CHANNELS
string providerName;
#endif
- ResourceManager? resources; // Look up localized strings here.
+ ResourceManager? resources; // Look up localized strings here.
EventManifestOptions flags;
IList<string> errors; // list of currently encountered errors
Dictionary<string, List<int>> perEventByteArrayArgIndices; // "event_name" -> List_of_Indices_of_Byte[]_Arg
- // State we track between StartEvent and EndEvent.
- string? eventName; // Name of the event currently being processed.
- int numParams; // keeps track of the number of args the event has.
+ // State we track between StartEvent and EndEvent.
+ string? eventName; // Name of the event currently being processed.
+ int numParams; // keeps track of the number of args the event has.
List<int>? byteArrArgIndices; // keeps track of the index of each byte[] argument
#endregion
}
/// <summary>
- /// Used to send the m_rawManifest into the event dispatcher as a series of events.
+ /// Used to send the m_rawManifest into the event dispatcher as a series of events.
/// </summary>
internal struct ManifestEnvelope
{
public EventSourceException(string? message) : base(message) { }
/// <summary>
- /// Initializes a new instance of the EventSourceException class with a specified error message
+ /// Initializes a new instance of the EventSourceException class with a specified error message
/// and a reference to the inner exception that is the cause of this exception.
/// </summary>
public EventSourceException(string? message, Exception? innerException) : base(message, innerException) { }
ThreadPoolDequeueWork((long)*((void**)Unsafe.AsPointer(ref workID)));
}
- // id - represents a correlation ID that allows correlation of two activities, one stamped by
+ // id - represents a correlation ID that allows correlation of two activities, one stamped by
// ThreadTransferSend, the other by ThreadTransferReceive
// kind - identifies the transfer: values below 64 are reserved for the runtime. Currently used values:
// 1 - managed Timers ("roaming" ID)
ThreadTransferSend((long)*((void**)Unsafe.AsPointer(ref id)), kind, info, multiDequeues, intInfo1, intInfo2);
}
- // id - represents a correlation ID that allows correlation of two activities, one stamped by
+ // id - represents a correlation ID that allows correlation of two activities, one stamped by
// ThreadTransferSend, the other by ThreadTransferReceive
// kind - identifies the transfer: values below 64 are reserved for the runtime. Currently used values:
// 1 - managed Timers ("roaming" ID)
}
}
}
-
#endif
{
/// <summary>
- /// IncrementingEventCounter is a variant of EventCounter for variables that are ever-increasing.
+ /// IncrementingEventCounter is a variant of EventCounter for variables that are ever-increasing.
/// Ex) # of exceptions in the runtime.
/// It does not calculate statistics like mean, standard deviation, etc. because it only accumulates
/// the counter value.
/// <summary>
/// Initializes a new instance of the <see cref="IncrementingEventCounter"/> class.
/// IncrementingEventCounter live as long as the EventSource that they are attached to unless they are
- /// explicitly Disposed.
+ /// explicitly Disposed.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="eventSource">The event source.</param>
}
/// <summary>
- /// Writes 'value' to the stream of values tracked by the counter. This updates the sum and other statistics that will
- /// be logged on the next timer interval.
+ /// Writes 'value' to the stream of values tracked by the counter. This updates the sum and other statistics that will
+ /// be logged on the next timer interval.
/// </summary>
/// <param name="increment">The value to increment by.</param>
public void Increment(double increment = 1)
#endif
{
/// <summary>
- /// IncrementingPollingCounter is a variant of EventCounter for variables that are ever-increasing.
+ /// IncrementingPollingCounter is a variant of EventCounter for variables that are ever-increasing.
/// Ex) # of exceptions in the runtime.
/// It does not calculate statistics like mean, standard deviation, etc. because it only accumulates
/// the counter value.
- /// Unlike IncrementingEventCounter, this takes in a polling callback that it can call to update
+ /// Unlike IncrementingEventCounter, this takes in a polling callback that it can call to update
/// its own metric periodically.
/// </summary>
public partial class IncrementingPollingCounter : DiagnosticCounter
/// <summary>
/// Initializes a new instance of the <see cref="IncrementingPollingCounter"/> class.
/// IncrementingPollingCounter live as long as the EventSource that they are attached to unless they are
- /// explicitly Disposed.
+ /// explicitly Disposed.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="eventSource">The event source.</param>
private Func<double> _totalValueProvider;
/// <summary>
- /// Calls "_totalValueProvider" to enqueue the counter value to the queue.
+ /// Calls "_totalValueProvider" to enqueue the counter value to the queue.
/// </summary>
internal void UpdateMetric()
{
#endif
{
/// <summary>
- /// PollingCounter is a variant of EventCounter - it collects and calculates similar statistics
+ /// PollingCounter is a variant of EventCounter - it collects and calculates similar statistics
/// as EventCounter. PollingCounter differs from EventCounter in that it takes in a callback
- /// function to collect metrics on its own rather than the user having to call WriteMetric()
+ /// function to collect metrics on its own rather than the user having to call WriteMetric()
/// every time.
/// </summary>
public partial class PollingCounter : DiagnosticCounter
lock (this)
{
double value = 0;
- try
+ try
{
value = _metricProvider();
}
Public = 0x10, // Include Public members in search
NonPublic = 0x20, // Include Non-Public members in search
}
-
+
public enum TypeCode {
Empty = 0, // Null reference
Object = 1, // Instance that isn't a value
}
public static MethodInfo? GetGetMethod(this PropertyInfo propInfo) { return propInfo.GetMethod; }
public static Type[] GetGenericArguments(this Type type) { return type.GenericTypeArguments; }
-
+
public static MethodInfo[] GetMethods(this Type type, BindingFlags flags)
{
// Minimal implementation to cover only the cases we need
}
return ti == null ? null : ti.AsType();
}
- public static TypeCode GetTypeCode(this Type type)
+ public static TypeCode GetTypeCode(this Type type)
{
if (type == typeof(bool)) return TypeCode.Boolean;
else if (type == typeof(byte)) return TypeCode.Byte;
private GCHandle* pins;
private byte[]? buffer;
private int bufferPos;
- private int bufferNesting; // We may merge many fields int a single blob. If we are doing this we increment this.
+ private int bufferNesting; // We may merge many fields int a single blob. If we are doing this we increment this.
private bool writingScalars;
internal void Enable(
/// <summary>
/// Gets or sets the name to use if this type is used for an
/// implicitly-named event or an implicitly-named property.
- ///
+ ///
/// Example 1:
- ///
+ ///
/// EventSource.Write(null, new T()); // implicitly-named event
- ///
+ ///
/// The name of the event will be determined as follows:
- ///
+ ///
/// if (T has an EventData attribute and attribute.Name != null)
/// eventName = attribute.Name;
/// else
/// eventName = typeof(T).Name;
- ///
+ ///
/// Example 2:
- ///
+ ///
/// EventSource.Write(name, new { _1 = new T() }); // implicitly-named field
- ///
+ ///
/// The name of the field will be determined as follows:
- ///
+ ///
/// if (T has an EventData attribute and attribute.Name != null)
/// fieldName = attribute.Name;
/// else
/// a sub-object (a field or property), and the sub-object's type has a
/// TraceLoggingEvent attribute, the Level from the sub-object's attribute
/// can affect the event's level.
- ///
+ ///
/// Example: for EventSource.Write(name, options, data), the level of the
/// event will be determined as follows:
- ///
+ ///
/// if (options.Level has been set)
/// eventLevel = options.Level;
/// else if (data.GetType() has a TraceLoggingEvent attribute and attribute.Level has been set)
/// a sub-object (a field or property), and the sub-object's type has a
/// TraceLoggingEvent attribute, the Opcode from the sub-object's attribute
/// can affect the event's opcode.
- ///
+ ///
/// Example: for EventSource.Write(name, options, data), the opcode of the
/// event will be determined as follows:
- ///
+ ///
/// if (options.Opcode has been set)
/// eventOpcode = options.Opcode;
/// else if (data.GetType() has a TraceLoggingEvent attribute and attribute.Opcode has been set)
/// a sub-object (a field or property), and the sub-object's type has a
/// TraceLoggingEvent attribute, the Keywords from the sub-object's attribute
/// can affect the event's keywords.
- ///
+ ///
/// Example: for EventSource.Write(name, options, data), the keywords of the
/// event will be determined as follows:
- ///
+ ///
/// eventKeywords = options.Keywords;
/// if (data.GetType() has a TraceLoggingEvent attribute)
/// eventKeywords |= attribute.Keywords;
/// Field receives default formatting based on the field's underlying type.
/// </summary>
Default = 0,
-#if false
+#if false
/// <summary>
/// Field should not be displayed.
/// </summary>
/// </summary>
Hexadecimal = 4,
-#if false
+#if false
/// <summary>
/// Field should be formatted as a process identifier. Typically applied to
/// 32-bit integer types.
/// strings or arrays of 8-bit or 16-bit integers.
/// </summary>
Json = 12,
-#if false
+#if false
/// <summary>
/// Field should be formatted as a Win32 error code. Typically applied to
/// 32-bit integer types.
/// 32-bit integer types.
/// </summary>
HResult = 15,
-#if false
+#if false
/// <summary>
/// Field should be formatted as a FILETIME. Typically applied to 64-bit
/// integer types. This is the default format for DateTime types.
#endif
{
/// <summary>
- /// EventPayload class holds the list of parameters and their corresponding values for user defined types passed to
+ /// EventPayload class holds the list of parameters and their corresponding values for user defined types passed to
/// EventSource APIs.
/// Preserving the order of the elements as they were found inside user defined types is the most important characteristic of this class.
/// </summary>
internal class EventPayload : IDictionary<string, object?>
{
- internal EventPayload(List<string> payloadNames, List<object?> payloadValues)
+ internal EventPayload(List<string> payloadNames, List<object?> payloadValues)
{
Debug.Assert(payloadNames.Count == payloadValues.Count);
int position = 0;
foreach(var name in m_names)
- {
+ {
if (name == key)
{
return m_values[position];
{
throw new System.NotSupportedException();
}
-
+
public bool Remove(string key)
{
throw new System.NotSupportedException();
{
throw new System.NotSupportedException();
}
-
+
public bool TryGetValue(string key, [MaybeNullWhen(false)] out object? value)
{
if (key == null)
}
/// <summary>
- /// You can make an activity out of just an EventSource.
+ /// You can make an activity out of just an EventSource.
/// </summary>
public static implicit operator EventSourceActivity(EventSource eventSource) { return new EventSourceActivity(eventSource); }
get { return this.activityId; }
}
-#if false // don't expose RelatedActivityId unless there is a need.
+#if false // don't expose RelatedActivityId unless there is a need.
/// <summary>
/// Gets the unique identifier of this activity's related (parent)
/// activity.
#endif
/// <summary>
- /// Writes a Start event with the specified name and data. If the start event is not active (because the provider
+ /// Writes a Start event with the specified name and data. If the start event is not active (because the provider
/// is not on or keyword-level indicates the event is off, then the returned activity is simply the 'this' pointer
/// and it is effectively like start did not get called.
- ///
+ ///
/// A new activityID GUID is generated and the returned
/// EventSourceActivity remembers this activity and will mark every event (including the start stop and any writes)
/// with this activityID. In addition the Start activity will log a 'relatedActivityID' that was the activity
/// ID before the start event. This way event processors can form a linked list of all the activities that
- /// caused this one (directly or indirectly).
+ /// caused this one (directly or indirectly).
/// </summary>
/// <param name="eventName">
- /// The name to use for the event. It is strongly suggested that this name end in 'Start' (e.g. DownloadStart).
- /// If you do this, then the Stop() method will automatically replace the 'Start' suffix with a 'Stop' suffix.
+ /// The name to use for the event. It is strongly suggested that this name end in 'Start' (e.g. DownloadStart).
+ /// If you do this, then the Stop() method will automatically replace the 'Start' suffix with a 'Stop' suffix.
/// </param>
- /// <param name="options">Allow options (keywords, level) to be set for the write associated with this start
+ /// <param name="options">Allow options (keywords, level) to be set for the write associated with this start
/// These will also be used for the stop event.</param>
/// <param name="data">The data to include in the event.</param>
public EventSourceActivity Start<T>(string? eventName, EventSourceOptions options, T data)
return this.Start(eventName, ref options, ref data);
}
/// <summary>
- /// Shortcut version see Start(string eventName, EventSourceOptions options, T data) Options is empty (no keywords
- /// and level==Info) Data payload is empty.
+ /// Shortcut version see Start(string eventName, EventSourceOptions options, T data) Options is empty (no keywords
+ /// and level==Info) Data payload is empty.
/// </summary>
public EventSourceActivity Start(string? eventName)
{
return this.Start(eventName, ref options, ref data);
}
/// <summary>
- /// Shortcut version see Start(string eventName, EventSourceOptions options, T data). Data payload is empty.
+ /// Shortcut version see Start(string eventName, EventSourceOptions options, T data). Data payload is empty.
/// </summary>
public EventSourceActivity Start(string? eventName, EventSourceOptions options)
{
return this.Start(eventName, ref options, ref data);
}
/// <summary>
- /// Shortcut version see Start(string eventName, EventSourceOptions options, T data) Options is empty (no keywords
- /// and level==Info)
+ /// Shortcut version see Start(string eventName, EventSourceOptions options, T data) Options is empty (no keywords
+ /// and level==Info)
/// </summary>
public EventSourceActivity Start<T>(string? eventName, T data)
{
/// Writes a Stop event with the specified data, and sets the activity
/// to the Stopped state. The name is determined by the eventName used in Start.
/// If that Start event name is suffixed with 'Start' that is removed, and regardless
- /// 'Stop' is appended to the result to form the Stop event name.
+ /// 'Stop' is appended to the result to form the Stop event name.
/// May only be called when the activity is in the Started state.
/// </summary>
/// <param name="data">The data to include in the event.</param>
/// <summary>
/// Used if you wish to use the non-default stop name (which is the start name with Start replace with 'Stop')
/// This can be useful to indicate unusual ways of stopping (but it is still STRONGLY recommended that
- /// you start with the same prefix used for the start event and you end with the 'Stop' suffix.
+ /// you start with the same prefix used for the start event and you end with the 'Stop' suffix.
/// </summary>
public void Stop<T>(string? eventName)
{
/// <summary>
/// Used if you wish to use the non-default stop name (which is the start name with Start replace with 'Stop')
/// This can be useful to indicate unusual ways of stopping (but it is still STRONGLY recommended that
- /// you start with the same prefix used for the start event and you end with the 'Stop' suffix.
+ /// you start with the same prefix used for the start event and you end with the 'Stop' suffix.
/// </summary>
public void Stop<T>(string? eventName, T data)
{
}
/// <summary>
- /// Writes an event associated with this activity to the eventSource associated with this activity.
+ /// Writes an event associated with this activity to the eventSource associated with this activity.
/// May only be called when the activity is in the Started state.
/// </summary>
/// <param name="eventName">
this.Write(this.eventSource, eventName, ref options, ref data);
}
/// <summary>
- /// Writes an event to a arbitrary eventSource stamped with the activity ID of this activity.
+ /// Writes an event to a arbitrary eventSource stamped with the activity ID of this activity.
/// </summary>
public void Write<T>(EventSource source, string? eventName, EventSourceOptions options, T data)
{
if (this.state != State.Started)
throw new InvalidOperationException();
- // If the source is not on at all, then we don't need to do anything and we can simply return ourselves.
+ // If the source is not on at all, then we don't need to do anything and we can simply return ourselves.
if (!this.eventSource.IsEnabled())
return this;
}
else
{
- // If we are not active, we don't set the eventName, which basically also turns off the Stop event as well.
+ // If we are not active, we don't set the eventName, which basically also turns off the Stop event as well.
newActivity.activityId = this.Id;
}
private void Write<T>(EventSource eventSource, string? eventName, ref EventSourceOptions options, ref T data)
{
if (this.state != State.Started)
- throw new InvalidOperationException(); // Write after stop.
+ throw new InvalidOperationException(); // Write after stop.
if (eventName == null)
throw new ArgumentNullException();
if (this.state != State.Started)
throw new InvalidOperationException();
- // If start was not fired, then stop isn't as well.
+ // If start was not fired, then stop isn't as well.
if (!StartEventWasFired)
return;
}
/// <summary>
- /// If eventName is non-null then we logged a start event
+ /// If eventName is non-null then we logged a start event
/// </summary>
private bool StartEventWasFired { get { return eventName != null; } }
private readonly string name;
/// <summary>
- /// The number of bytes in the UTF8 Encoding of 'name' INCLUDING a null terminator.
+ /// The number of bytes in the UTF8 Encoding of 'name' INCLUDING a null terminator.
/// </summary>
private readonly int nameSize;
private readonly EventFieldTags tags;
/// <summary>
/// This is the main routine for FieldMetaData. Basically it will serialize the data in
/// this structure as TraceLogging style meta-data into the array 'metaArray' starting at
- /// 'pos' (pos is updated to reflect the bytes written).
- ///
+ /// 'pos' (pos is updated to reflect the bytes written).
+ ///
/// Note that 'metaData' can be null, in which case it only updates 'pos'. This is useful
/// for a 'two pass' approach where you figure out how big to make the array, and then you
- /// fill it in.
+ /// fill it in.
/// </summary>
public void Encode(ref int pos, byte[]? metadata)
{
}
pos += 2;
- // If InTypeCustomCountFlag set, write out the blob of custom meta-data.
+ // If InTypeCustomCountFlag set, write out the blob of custom meta-data.
if (Statics.InTypeCustomCountFlag == (this.inType & Statics.InTypeCountMask) &&
this.fixedCount != 0)
{
{
/// <summary>
/// Insure that eventIds strictly less than 'eventId' will not be
- /// used by the SelfDescribing events.
+ /// used by the SelfDescribing events.
/// </summary>
internal static void ReserveEventIDsBelow(int eventId)
{
{
int snapshot = lastIdentity;
int newIdentity = (lastIdentity & ~0xFFFFFF) + eventId;
- newIdentity = Math.Max(newIdentity, snapshot); // Should be redundant. as we only create descriptors once.
+ newIdentity = Math.Max(newIdentity, snapshot); // Should be redundant. as we only create descriptors once.
if (Interlocked.CompareExchange(ref lastIdentity, newIdentity, snapshot) == snapshot)
break;
}
/// <summary>
/// Holds property values of any type. For common value types, we have inline storage so that we don't need
/// to box the values. For all other types, we store the value in a single object reference field.
- ///
+ ///
/// To get the value of a property quickly, use a delegate produced by <see cref="PropertyValue.GetPropertyGetter(PropertyInfo)"/>.
/// </summary>
#if ES_BUILD_PN
private ScalarTypeInfo(
Type type,
Func<EventFieldFormat, TraceLoggingDataType, TraceLoggingDataType> formatFunc,
- TraceLoggingDataType nativeFormat)
+ TraceLoggingDataType nativeFormat)
: base(type)
{
this.formatFunc = formatFunc;
Type type,
Func<EventFieldFormat, TraceLoggingDataType, TraceLoggingDataType> formatFunc,
TraceLoggingDataType nativeFormat,
- int elementSize)
+ int elementSize)
: base(type)
{
this.formatFunc = formatFunc;
{
collector.AddNullTerminatedString((string?)value.ReferenceValue);
}
-
+
public override object GetData(object? value)
{
if (value == null)
{
return "";
}
-
+
return value;
}
}
/// starting at the index given by pos. Updates pos. Writes 1 to 4 bytes,
/// depending on the value of the tags variable. Usable for event tags and
/// field tags.
- ///
+ ///
/// Note that 'metadata' can be null, in which case it only updates 'pos'.
/// This is useful for a two pass approach where you figure out how big to
- /// make the array, and then you fill it in.
+ /// make the array, and then you fill it in.
/// </summary>
public static void EncodeTags(int tags, ref int pos, byte[]? metadata)
{
return TraceLoggingDataType.Boolean8;
case EventFieldFormat.Hexadecimal:
return TraceLoggingDataType.HexInt8;
-#if false
+#if false
case EventSourceFieldFormat.Signed:
return TraceLoggingDataType.Int8;
case EventSourceFieldFormat.Unsigned:
return TraceLoggingDataType.Boolean32;
case EventFieldFormat.Hexadecimal:
return TraceLoggingDataType.HexInt32;
-#if false
+#if false
case EventSourceFieldFormat.Ipv4Address:
return TraceLoggingDataType.Ipv4Address;
case EventSourceFieldFormat.ProcessId:
#endif
case EventFieldFormat.HResult:
return TraceLoggingDataType.HResult;
-#if false
+#if false
case EventSourceFieldFormat.Signed:
return TraceLoggingDataType.Int32;
case EventSourceFieldFormat.Unsigned:
return native;
case EventFieldFormat.Hexadecimal:
return TraceLoggingDataType.HexInt64;
-#if false
+#if false
case EventSourceFieldFormat.FileTime:
return TraceLoggingDataType.FileTime;
case EventSourceFieldFormat.Signed:
return native;
case EventFieldFormat.Hexadecimal:
return HexIntPtrType;
-#if false
+#if false
case EventSourceFieldFormat.Signed:
return IntPtrType;
case EventSourceFieldFormat.Unsigned:
/// </summary>
HexInt16 = UInt16 + (EventFieldFormat.Hexadecimal << 8),
-#if false
+#if false
/// <summary>
/// Formatted type.
/// Encoding assumes 32-bit value.
/// Decoding treats as MBCS JSON.
/// </summary>
CountedMbcsJson = CountedMbcsString + (EventFieldFormat.Json << 8),
-#if false
+#if false
/// <summary>
/// Formatted type.
/// Encoding assumes 32-bit value.
// See the LICENSE file in the project root for more information.
// This program uses code hyperlinks available as part of the HyperAddin Visual Studio plug-in.
-// It is available from http://www.codeplex.com/hyperAddin
+// It is available from http://www.codeplex.com/hyperAddin
#if PLATFORM_WINDOWS
#define FEATURE_MANAGED_ETW
/// The name of the event source. Must not be null.
/// </param>
/// <param name="config">
- /// Configuration options for the EventSource as a whole.
+ /// Configuration options for the EventSource as a whole.
/// </param>
public EventSource(
string eventSourceName,
/// <summary>
/// Construct an EventSource with a given name for non-contract based events (e.g. those using the Write() API).
- ///
- /// Also specify a list of key-value pairs called traits (you must pass an even number of strings).
+ ///
+ /// Also specify a list of key-value pairs called traits (you must pass an even number of strings).
/// The first string is the key and the second is the value. These are not interpreted by EventSource
- /// itself but may be interpreted the listeners. Can be fetched with GetTrait(string).
+ /// itself but may be interpreted the listeners. Can be fetched with GetTrait(string).
/// </summary>
/// <param name="eventSourceName">
/// The name of the event source. Must not be null.
/// </param>
/// <param name="config">
- /// Configuration options for the EventSource as a whole.
+ /// Configuration options for the EventSource as a whole.
/// </param>
/// <param name="traits">A collection of key-value strings (must be an even number).</param>
public EventSource(
/// <summary>
/// Writes an event.
/// This overload is meant for clients that need to manipuate the activityId
- /// and related ActivityId for the event.
+ /// and related ActivityId for the event.
/// </summary>
/// <typeparam name="T">
/// The type that defines the event and its payload. This must be an
/// saved. It should not be recreated for each event.
/// </param>
/// <param name="activityID">
- /// A pointer to the activity ID GUID to log
+ /// A pointer to the activity ID GUID to log
/// </param>
/// <param name="childActivityID">
/// A pointer to the child activity ID to log (can be null) </param>
/// combined properties of any number of values. This method is
/// intended for use in advanced logging scenarios that support a
/// dynamic set of event context providers.
- /// Attention: This API does not check whether the event is enabled or not.
- /// Please use WriteMultiMerge to avoid spending CPU cycles for events that are
+ /// Attention: This API does not check whether the event is enabled or not.
+ /// Please use WriteMultiMerge to avoid spending CPU cycles for events that are
/// not enabled.
/// </summary>
/// <param name="eventName">
/// saved. It should not be recreated for each event.
/// </param>
/// <param name="activityID">
- /// A pointer to the activity ID GUID to log
+ /// A pointer to the activity ID GUID to log
/// </param>
/// <param name="childActivityID">
/// A pointer to the child activity ID to log (can be null)
/// saved. It should not be recreated for each event.
/// </param>
/// <param name="activityID">
- /// A pointer to the activity ID GUID to log
+ /// A pointer to the activity ID GUID to log
/// </param>
/// <param name="childActivityID">
/// A pointer to the child activity ID to log (can be null)
- /// </param>
+ /// </param>
/// <param name="data">
/// The previously serialized values to include in the event. Must not be null.
- /// The number and types of the values must match the number and types of the
+ /// The number and types of the values must match the number and types of the
/// fields described by the eventTypes parameter.
/// </param>
internal unsafe void WriteMultiMerge(
#endif
// We make a descriptor for each EventData, and because we morph strings to counted strings
- // we may have 2 for each arg, so we allocate enough for this.
+ // we may have 2 for each arg, so we allocate enough for this.
var descriptorsLength = eventTypes.dataCount + eventTypes.typeInfos.Length * 2 + 3;
var descriptors = stackalloc EventData[descriptorsLength];
for(int i = 0; i < descriptorsLength; i++)
}
string value = m_traits[i + 1];
int lenPos = traitMetaData.Count;
- traitMetaData.Add(0); // Emit size (to be filled in later)
+ traitMetaData.Add(0); // Emit size (to be filled in later)
traitMetaData.Add(0);
traitMetaData.Add(traitNum); // Emit Trait number
- var valueLen = AddValueToMetaData(traitMetaData, value) + 3; // Emit the value bytes +3 accounts for 3 bytes we emited above.
+ var valueLen = AddValueToMetaData(traitMetaData, value) + 3; // Emit the value bytes +3 accounts for 3 bytes we emited above.
traitMetaData[lenPos] = unchecked((byte)valueLen); // Fill in size
traitMetaData[lenPos + 1] = unchecked((byte)(valueLen >> 8));
}
{
for (int i = 1; i < value.Length; i++)
{
- if (value[i] != ' ') // Skip spaces between bytes.
+ if (value[i] != ' ') // Skip spaces between bytes.
{
if (!(i + 1 < value.Length))
{
}
}
}
- else if ('A' <= firstChar || ' ' == firstChar) // Is it alphabetic or space (excludes digits and most punctuation).
+ else if ('A' <= firstChar || ' ' == firstChar) // Is it alphabetic or space (excludes digits and most punctuation).
{
metaData.AddRange(Encoding.UTF8.GetBytes(value));
}
}
/// <summary>
- /// Returns a value 0-15 if 'c' is a hexadecimal digit. If it throws an argument exception.
+ /// Returns a value 0-15 if 'c' is a hexadecimal digit. If it throws an argument exception.
/// </summary>
private static int HexDigit(char c)
{
{
return (c - 'A' + 10);
}
-
+
throw new ArgumentException(SR.Format(SR.EventSource_BadHexDigit, c), "traits");
}
PropertyValue value);
/// <summary>
- /// Fetches the event parameter data for internal serialization.
+ /// Fetches the event parameter data for internal serialization.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
/*============================================================
**
**
-** Purpose:
-** Contains eventing constants defined by the Windows
+** Purpose:
+** Contains eventing constants defined by the Windows
** environment.
-**
+**
============================================================*/
#if ES_BUILD_STANDALONE
#define FEATURE_MANAGED_ETW_CHANNELS
/// </summary>
Informational,
/// <summary>
- /// All events, including previous levels
+ /// All events, including previous levels
/// </summary>
Verbose
}
/// </summary>
Start,
/// <summary>
- /// An activity end event
+ /// An activity end event
/// </summary>
Stop,
/// <summary>
/// </summary>
Send,
/// <summary>
- /// An event representing receiving an activity transfer from another component
+ /// An event representing receiving an activity transfer from another component
/// </summary>
Receive = 240
}
public enum EventKeywords : long
{
/// <summary>
- /// No events.
+ /// No events.
/// </summary>
None = 0x0,
/// <summary>
- /// All Events
+ /// All Events
/// </summary>
All = ~0,
/// <summary>
namespace System
{
- // The DuplicateWaitObjectException is thrown when an object
+ // The DuplicateWaitObjectException is thrown when an object
// appears more than once in the list of objects to WaitAll or WaitAny.
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class DuplicateWaitObjectException : ArgumentException
{
- // Creates a new DuplicateWaitObjectException with its message
+ // Creates a new DuplicateWaitObjectException with its message
// string set to a default message.
public DuplicateWaitObjectException()
: base(SR.Arg_DuplicateWaitObjectException)
{
HResult = HResults.COR_E_DUPLICATEWAITOBJECT;
}
-
+
protected DuplicateWaitObjectException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
// Copy strings out, parsing into pairs and inserting into the table.
// The first few environment variable entries start with an '='.
// The current working directory of every drive (except for those drives
- // you haven't cd'ed into in your DOS window) are stored in the
- // environment block (as =C:=pwd) and the program's exit code is
+ // you haven't cd'ed into in your DOS window) are stored in the
+ // environment block (as =C:=pwd) and the program's exit code is
// as well (=ExitCode=00000000).
var results = new Hashtable();
int startKey = i;
// Skip to key. On some old OS, the environment block can be corrupted.
- // Some will not have '=', so we need to check for '\0'.
+ // Some will not have '=', so we need to check for '\0'.
while (block[i] != '=' && block[i] != '\0')
{
i++;
int startValue = i;
while (block[i] != 0)
{
- i++; // Read to end of this entry
+ i++; // Read to end of this entry
}
string value = new string(block.Slice(startValue, i - startValue)); // skip over 0 handled by for loop's i++
_message = message;
}
- // Creates a new Exception. All derived classes should
+ // Creates a new Exception. All derived classes should
// provide this constructor.
- // Note: the stack trace is not started until the exception
+ // Note: the stack trace is not started until the exception
// is thrown
- //
+ //
public Exception(string? message, Exception? innerException)
: this()
{
**
** Purpose: Exception to designate an illegal argument to FormatMessage.
**
-**
+**
===========================================================*/
using System.Runtime.Serialization;
}
/// <summary>
- /// Schedule 'callback' to be called in the next GC. If the callback returns true it is
- /// rescheduled for the next Gen 2 GC. Otherwise the callbacks stop.
- ///
+ /// Schedule 'callback' to be called in the next GC. If the callback returns true it is
+ /// rescheduled for the next Gen 2 GC. Otherwise the callbacks stop.
+ ///
/// NOTE: This callback will be kept alive until either the callback function returns false,
/// or the target object dies.
/// </summary>
private bool LoadCalendarDataFromSystem(string localeName, CalendarId calendarId)
{
bool result = true;
-
+
// these can return null but are later replaced with String.Empty or other non-nullable value
result &= GetCalendarInfo(localeName, calendarId, CalendarDataType.NativeName, out this.sNativeName!);
result &= GetCalendarInfo(localeName, calendarId, CalendarDataType.MonthDay, out this.sMonthDay!);
Debug.Assert(!GlobalizationMode.Invariant);
string data;
- // Taiwanese calendar get listed as one of the optional zh-TW calendars only when having zh-TW UI
+ // Taiwanese calendar get listed as one of the optional zh-TW calendars only when having zh-TW UI
return CallGetCalendarInfoEx("zh-TW", CalendarId.TAIWAN, CAL_SCALNAME, out data);
}
FirstFullWeek = 1, // Week 1 begins on first FirstDayOfWeek not before the first day of the year
- FirstFourDayWeek = 2 // Week 1 begins on first FirstDayOfWeek such that FirstDayOfWeek+3 is not before the first day of the year
+ FirstFourDayWeek = 2 // Week 1 begins on first FirstDayOfWeek such that FirstDayOfWeek+3 is not before the first day of the year
};
}
case CorrectionAlgorithm.Year1620to1699: return EphemerisCorrection1620to1699(year);
}
- break; // break the loop and assert eventually
+ break; // break the loop and assert eventually
}
}
byte [] keyData;
if (source.Length == 0)
- {
+ {
keyData = Array.Empty<byte>();
}
else
{
pShort[i] = (short) InvariantToUpper(source[i]);
}
- }
+ }
else
{
Buffer.MemoryCopy(pChar, pByte, keyData.Length, keyData.Length);
{
// Always map the "C" locale to Invariant to avoid mapping it to en_US_POSIX on Linux because POSIX
// locale collation doesn't support case insensitive comparisons.
- // We do the same mapping on Windows for the sake of consistency.
+ // We do the same mapping on Windows for the sake of consistency.
return CultureData.Invariant;
}
// See the LICENSE file in the project root for more information.
// The enumeration constants used in CultureInfo.GetCultures().
-// On Linux platforms, the only enum values used there is NeutralCultures and SpecificCultures
+// On Linux platforms, the only enum values used there is NeutralCultures and SpecificCultures
// the rest are obsolete or not valid on Linux
namespace System.Globalization
{
Context = 0x0000, // The shape depends on the previous text in the same output.
None = 0x0001, // Gives full Unicode compatibility.
- NativeNational = 0x0002 // National shapes
+ NativeNational = 0x0002 // National shapes
}
}
private readonly byte[] _keyData;
/// <summary>
- /// The following constructor is designed to be called from CompareInfo to get the
+ /// The following constructor is designed to be called from CompareInfo to get the
/// the sort key of specific string for synthetic culture
/// </summary>
internal SortKey(string localeName, string str, CompareOptions options, byte[] keyData)
{
partial struct Guid
{
- // This will create a new random guid based on the https://www.ietf.org/rfc/rfc4122.txt
+ // This will create a new random guid based on the https://www.ietf.org/rfc/rfc4122.txt
public static unsafe Guid NewGuid()
{
Guid g;
Interop.GetRandomBytes((byte*)&g, sizeof(Guid));
-
+
const ushort VersionMask = 0xF000;
const ushort RandomGuidVersion = 0x4000;
Guid g;
int hr = Interop.Ole32.CoCreateGuid(out g);
- // We don't expect that this will ever throw an error, none are even documented, and so we don't want to pull
- // in the HR to ComException mappings into the core library just for this so we will try a generic exception if
+ // We don't expect that this will ever throw an error, none are even documented, and so we don't want to pull
+ // in the HR to ComException mappings into the core library just for this so we will try a generic exception if
// we ever hit this condition.
if (hr != 0)
{
}
}
}
-
{
throw new OverflowException(SR.GetResourceString(failureMessageID));
}
-
+
throw new FormatException(SR.Format_GuidUnrecognized);
}
-
+
throw new FormatException(SR.GetResourceString(failureMessageID));
}
}
return guidString;
}
- // Returns whether the guid is successfully formatted as a span.
+ // Returns whether the guid is successfully formatted as a span.
public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format = default)
{
if (format.Length == 0)
format = "D";
}
// all acceptable format strings are of length 1
- if (format.Length != 1)
+ if (format.Length != 1)
{
throw new FormatException(SR.Format_InvalidGuidFormatSpecification);
}
//===========================================================================*/
// Note: FACILITY_URT is defined as 0x13 (0x8013xxxx). Within that
// range, 0x1yyy is for Runtime errors (used for Security, Metadata, etc).
-// In that subrange, 0x15zz and 0x16zz have been allocated for classlib-type
-// HResults. Also note that some of our HResults have to map to certain
+// In that subrange, 0x15zz and 0x16zz have been allocated for classlib-type
+// HResults. Also note that some of our HResults have to map to certain
// COM HR's, etc.
// Reflection will use 0x1600 -> 0x161f. IO will use 0x1620 -> 0x163f.
-// Licensed to the .NET Foundation under one or more agreements.
+// 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.
xxHash - Fast Hash algorithm
Copyright (C) 2012-2016, Yann Collet
-
+
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
-
+
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
-
+
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
-
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
+
You can contact the author at :
- xxHash homepage: http://www.xxhash.com
- xxHash source repository : https://github.com/Cyan4973/xxHash
// To see what's really going on here, have a look at the Combine
// methods.
-
+
var val = (uint)value;
-
+
// Storing the value of _length locally shaves of quite a few bytes
// in the resulting machine code.
uint previousLength = _length++;
// Storing the value of _length locally shaves of quite a few bytes
// in the resulting machine code.
uint length = _length;
-
+
// position refers to the *next* queue position in this method, so
// position == 1 means that _queue1 is populated; _queue2 would have
// been populated on the next call to Add.
}
#pragma warning disable 0809
- // Obsolete member 'memberA' overrides non-obsolete member 'memberB'.
+ // Obsolete member 'memberA' overrides non-obsolete member 'memberB'.
// Disallowing GetHashCode and Equals is by design
- // * We decided to not override GetHashCode() to produce the hash code
+ // * We decided to not override GetHashCode() to produce the hash code
// as this would be weird, both naming-wise as well as from a
// behavioral standpoint (GetHashCode() should return the object's
// hash code, not the one being computed).
// ordering of instances of the class. The ordering represented by
// IComparable can be used to sort arrays and collections of objects
// that implement the interface.
- //
+ //
public interface IComparable
{
// Interface does not need to be marked with the serializable attribute
// a value less than zero if this is less than object, zero
// if this is equal to object, or a value greater than zero
// if this is greater than object.
- //
+ //
int CompareTo(object? obj);
}
// a value less than zero if this is less than object, zero
// if this is equal to object, or a value greater than zero
// if this is greater than object.
- //
+ //
int CompareTo([AllowNull] T other);
}
}
// given type. If a particular conversion is not supported, the
// implementation must throw an InvalidCastException. If the value of the
// underlying object is not within the range of the target type, the
- // implementation must throw an OverflowException. The
+ // implementation must throw an OverflowException. The
// IFormatProvider? will be used to get a NumberFormatInfo or similar
// appropriate service object, and may safely be null.
object ToType(Type conversionType, IFormatProvider? provider);
}
}
-
**
** Purpose: Interface for assisting with deterministic finalization.
**
-**
+**
===========================================================*/
namespace System
// IDisposable is an attempt at helping to solve problems with deterministic
// finalization. The GC of course doesn't leave any way to deterministically
// know when a finalizer will run. This forces classes that hold onto OS
- // resources or some sort of important state (such as a FileStream or a
- // network connection) to provide a Close or Dispose method so users can
- // run clean up code deterministically. We have formalized this into an
+ // resources or some sort of important state (such as a FileStream or a
+ // network connection) to provide a Close or Dispose method so users can
+ // run clean up code deterministically. We have formalized this into an
// interface with one method. Classes may privately implement IDisposable and
// provide a Close method instead, if that name is by far the expected name
// for objects in that domain (ie, you don't Dispose of a FileStream, you Close
// it).
//
- // This interface could be theoretically used as a marker by a compiler to
- // ensure a disposable object has been cleaned up along all code paths if it's
- // been allocated in that method, though in practice any compiler that
+ // This interface could be theoretically used as a marker by a compiler to
+ // ensure a disposable object has been cleaned up along all code paths if it's
+ // been allocated in that method, though in practice any compiler that
// draconian may tick off any number of people. Perhaps an external tool (like
- // like Purify or BoundsChecker) could do this. Instead, C# has added a using
- // clause, which will generate a try/finally statement where the resource
- // passed into the using clause will always have it's Dispose method called.
+ // like Purify or BoundsChecker) could do this. Instead, C# has added a using
+ // clause, which will generate a try/finally statement where the resource
+ // passed into the using clause will always have it's Dispose method called.
// Syntax is using(FileStream fs = ...) { .. };
//
// Dispose should meet the following conditions:
// 3) Call the base class's Dispose method, if necessary
// 4) Suppress finalization of this class to help the GC by reducing the
// number of objects on the finalization queue.
- // 5) Dispose shouldn't generally throw exceptions, except for very serious
- // errors that are particularly unexpected. (ie, OutOfMemoryException)
+ // 5) Dispose shouldn't generally throw exceptions, except for very serious
+ // errors that are particularly unexpected. (ie, OutOfMemoryException)
// Ideally, nothing should go wrong with your object by calling Dispose.
//
// If possible, a class should define a finalizer that calls Dispose.
// However, in many situations, this is impractical. For instance, take the
- // classic example of a Stream and a StreamWriter (which has an internal
- // buffer of data to write to the Stream). If both objects are collected
+ // classic example of a Stream and a StreamWriter (which has an internal
+ // buffer of data to write to the Stream). If both objects are collected
// before Close or Dispose has been called on either, then the GC may run the
// finalizer for the Stream first, before the StreamWriter. At that point, any
// data buffered by the StreamWriter cannot be written to the Stream. In this
// case, it doesn't make much sense to provide a finalizer on the StreamWriter
- // since you cannot solve this problem correctly.
+ // since you cannot solve this problem correctly.
public interface IDisposable
{
void Dispose();
/*============================================================
**
-**
-**
+**
+**
**
**
** Purpose: Wraps a stream and provides convenient read functionality
private char[]? _charBuffer;
private int _maxCharsSize; // From MaxCharBytesSize & Encoding
- // Performance optimization for Read() w/ Unicode. Speeds us up by ~40%
+ // Performance optimization for Read() w/ Unicode. Speeds us up by ~40%
private bool _2BytesPerChar;
private bool _isMemoryStream; // "do we sit on MemoryStream?" for Read/ReadInt32 perf
private bool _leaveOpen;
_buffer = new byte[minBufferSize];
// _charBuffer and _charBytes will be left null.
- // For Encodings that always use 2 bytes per char (or more),
+ // For Encodings that always use 2 bytes per char (or more),
// special case them here to make Read() & Peek() faster.
_2BytesPerChar = encoding is UnicodeEncoding;
// check if BinaryReader is based on MemoryStream, and keep this for it's life
if (_charBytes == null)
{
- _charBytes = new byte[MaxCharBytesSize]; //REVIEW: We need at most 2 bytes/char here?
+ _charBytes = new byte[MaxCharBytesSize]; //REVIEW: We need at most 2 bytes/char here?
}
Span<char> singleChar = stackalloc char[1];
}
catch
{
- // Handle surrogate char
+ // Handle surrogate char
if (_stream.CanSeek)
{
// this should never fail
Debug.Assert(charsRemaining >= 0, "We read too many characters.");
- // we may have read fewer than the number of characters requested if end of stream reached
+ // we may have read fewer than the number of characters requested if end of stream reached
// or if the encoding makes the char count too big for the buffer (e.g. fallback sequence)
return (buffer.Length - charsRemaining);
}
// Closes this writer and releases any system resources associated with the
// writer. Following a call to Close, any operations on the writer
- // may raise exceptions.
+ // may raise exceptions.
public virtual void Close()
{
Dispose(true);
}
// Clears all buffers for this writer and causes any buffered data to be
- // written to the underlying device.
+ // written to the underlying device.
public virtual void Flush()
{
OutStream.Flush();
// Writes a boolean to this stream. A single byte is written to the stream
// with the value 0 representing false or the value 1 representing true.
- //
+ //
public virtual void Write(bool value)
{
_buffer[0] = (byte)(value ? 1 : 0);
// Writes a byte to this stream. The current position of the stream is
// advanced by one.
- //
+ //
public virtual void Write(byte value)
{
OutStream.WriteByte(value);
}
- // Writes a signed byte to this stream. The current position of the stream
+ // Writes a signed byte to this stream. The current position of the stream
// is advanced by one.
- //
+ //
[CLSCompliant(false)]
public virtual void Write(sbyte value)
{
}
// Writes a byte array to this stream.
- //
+ //
// This default implementation calls the Write(Object, int, int)
// method to write the byte array.
- //
+ //
public virtual void Write(byte[] buffer)
{
if (buffer == null)
//
// This default implementation calls the Write(Object, int, int)
// method to write the byte array.
- //
+ //
public virtual void Write(byte[] buffer, int index, int count)
{
OutStream.Write(buffer, index, count);
// Writes a character to this stream. The current position of the stream is
// advanced by two.
// Note this method cannot handle surrogates properly in UTF-8.
- //
+ //
public unsafe virtual void Write(char ch)
{
if (char.IsSurrogate(ch))
}
// Writes a character array to this stream.
- //
+ //
// This default implementation calls the Write(Object, int, int)
// method to write the character array.
- //
+ //
public virtual void Write(char[] chars)
{
if (chars == null)
//
// This default implementation calls the Write(Object, int, int)
// method to write the character array.
- //
+ //
public virtual void Write(char[] chars, int index, int count)
{
byte[] bytes = _encoding.GetBytes(chars, index, count);
// Writes a double to this stream. The current position of the stream is
// advanced by eight.
- //
+ //
public unsafe virtual void Write(double value)
{
ulong TmpValue = *(ulong*)&value;
// Writes a two-byte signed integer to this stream. The current position of
// the stream is advanced by two.
- //
+ //
public virtual void Write(short value)
{
_buffer[0] = (byte)value;
// Writes a two-byte unsigned integer to this stream. The current position
// of the stream is advanced by two.
- //
+ //
[CLSCompliant(false)]
public virtual void Write(ushort value)
{
// Writes a four-byte signed integer to this stream. The current position
// of the stream is advanced by four.
- //
+ //
public virtual void Write(int value)
{
_buffer[0] = (byte)value;
// Writes a four-byte unsigned integer to this stream. The current position
// of the stream is advanced by four.
- //
+ //
[CLSCompliant(false)]
public virtual void Write(uint value)
{
// Writes an eight-byte signed integer to this stream. The current position
// of the stream is advanced by eight.
- //
+ //
public virtual void Write(long value)
{
_buffer[0] = (byte)value;
OutStream.Write(_buffer, 0, 8);
}
- // Writes an eight-byte unsigned integer to this stream. The current
+ // Writes an eight-byte unsigned integer to this stream. The current
// position of the stream is advanced by eight.
- //
+ //
[CLSCompliant(false)]
public virtual void Write(ulong value)
{
// Writes a float to this stream. The current position of the stream is
// advanced by four.
- //
+ //
public unsafe virtual void Write(float value)
{
uint TmpValue = *(uint*)&value;
// Writes a length-prefixed string to this stream in the BinaryWriter's
- // current Encoding. This method first writes the length of the string as
- // a four-byte unsigned integer, and then writes that many characters
+ // current Encoding. This method first writes the length of the string as
+ // a four-byte unsigned integer, and then writes that many characters
// to the stream.
- //
+ //
public unsafe virtual void Write(string value)
{
if (value == null)
else
{
// Aggressively try to not allocate memory in this loop for
- // runtime performance reasons. Use an Encoder to write out
+ // runtime performance reasons. Use an Encoder to write out
// the string correctly (handling surrogates crossing buffer
- // boundaries properly).
+ // boundaries properly).
int charStart = 0;
int numLeft = value.Length;
#if DEBUG
{
/*
* Thrown when trying to access a directory that doesn't exist on disk.
- * From COM Interop, this exception is thrown for 2 HRESULTS:
- * the Win32 errorcode-as-HRESULT ERROR_PATH_NOT_FOUND (0x80070003)
+ * From COM Interop, this exception is thrown for 2 HRESULTS:
+ * the Win32 errorcode-as-HRESULT ERROR_PATH_NOT_FOUND (0x80070003)
* and STG_E_PATHNOTFOUND (0x80030003).
*/
[Serializable]
throw Win32Marshal.GetExceptionForLastWin32Error();
}
- // GetLogicalDrives returns a bitmask starting from
+ // GetLogicalDrives returns a bitmask starting from
// position 0 "A" indicating whether a drive is present.
// Loop over each bit, creating a string for each one
// that is set.
{
// Contains constants for specifying the access you want for a file.
// You can have Read, Write or ReadWrite access.
- //
+ //
[Flags]
public enum FileAccess
{
Write = 2,
// Specifies read and write access to the file. Data can be written to the
- // file and the file pointer can be moved. Data can also be read from the
+ // file and the file pointer can be moved. Data can also be read from the
// file.
ReadWrite = 3,
}
// Contains constants for specifying how the OS should open a file.
// These will control whether you overwrite a file, open an existing
// file, or some combination thereof.
- //
+ //
// To append to a file, use Append (which maps to OpenOrCreate then we seek
- // to the end of the file). To truncate a file or create it if it doesn't
+ // to the end of the file). To truncate a file or create it if it doesn't
// exist, use Create.
- //
+ //
public enum FileMode
{
// Creates a new file. An exception is raised if the file already exists.
// WRITE access. An exception is raised if the file does not exist.
Truncate = 5,
- // Opens the file if it exists and seeks to the end. Otherwise,
+ // Opens the file if it exists and seeks to the end. Otherwise,
// creates a new file.
Append = 6,
}
HResult = HResults.COR_E_FILENOTFOUND;
}
- public FileNotFoundException(string? message, string? fileName)
+ public FileNotFoundException(string? message, string? fileName)
: base(message)
{
HResult = HResults.COR_E_FILENOTFOUND;
}
}
}
-
namespace System.IO
{
// Maps to FILE_FLAG_DELETE_ON_CLOSE and similar values from winbase.h.
- // We didn't expose a number of these values because we didn't believe
+ // We didn't expose a number of these values because we didn't believe
// a number of them made sense in managed code, at least not yet.
[Flags]
public enum FileOptions
{
- // NOTE: any change to FileOptions enum needs to be
+ // NOTE: any change to FileOptions enum needs to be
// matched in the FileStream ctor for error validation
None = 0,
WriteThrough = unchecked((int)0x80000000),
Encrypted = 0x00004000, // FILE_ATTRIBUTE_ENCRYPTED
}
}
-
//
// Note these values currently match the values for FILE_SHARE_READ,
// FILE_SHARE_WRITE, and FILE_SHARE_DELETE in winnt.h
- //
+ //
[Flags]
public enum FileShare
{
// Translate the arguments into arguments for an open call.
Interop.Sys.OpenFlags openFlags = PreOpenConfigurationFromOptions(mode, _access, share, options);
- // If the file gets created a new, we'll select the permissions for it. Most Unix utilities by default use 666 (read and
+ // If the file gets created a new, we'll select the permissions for it. Most Unix utilities by default use 666 (read and
// write for all), so we do the same (even though this doesn't match Windows, where by default it's possible to write out
// a file and then execute it). No matter what we choose, it'll be subject to the umask applied by the system, such that the
// actual permissions will typically be less than what we select here.
{
_fileHandle.IsAsync = _useAsyncIO;
- // Lock the file if requested via FileShare. This is only advisory locking. FileShare.None implies an exclusive
- // lock on the file and all other modes use a shared lock. While this is not as granular as Windows, not mandatory,
+ // Lock the file if requested via FileShare. This is only advisory locking. FileShare.None implies an exclusive
+ // lock on the file and all other modes use a shared lock. While this is not as granular as Windows, not mandatory,
// and not atomic with file opening, it's better than nothing.
Interop.Sys.LockOperations lockOperation = (share == FileShare.None) ? Interop.Sys.LockOperations.LOCK_EX : Interop.Sys.LockOperations.LOCK_SH;
if (Interop.Sys.FLock(_fileHandle, lockOperation | Interop.Sys.LockOperations.LOCK_NB) < 0)
return Task.FromException(e);
}
- // We then separately flush to disk asynchronously. This is only
+ // We then separately flush to disk asynchronously. This is only
// necessary if we support writing; otherwise, we're done.
if (CanWrite)
{
// We may not have had enough data in the buffer to completely satisfy the user's request.
// While Read doesn't require that we return as much data as the user requested (any amount
- // up to the requested count is fine), FileStream on Windows tries to do so by doing a
- // subsequent read from the file if we tried to satisfy the request with what was in the
- // buffer but the buffer contained less than the requested count. To be consistent with that
- // behavior, we do the same thing here on Unix. Note that we may still get less the requested
- // amount, as the OS may give us back fewer than we request, either due to reaching the end of
+ // up to the requested count is fine), FileStream on Windows tries to do so by doing a
+ // subsequent read from the file if we tried to satisfy the request with what was in the
+ // buffer but the buffer contained less than the requested count. To be consistent with that
+ // behavior, we do the same thing here on Unix. Note that we may still get less the requested
+ // amount, as the OS may give us back fewer than we request, either due to reaching the end of
// file, or due to its own whims.
if (!readFromOS && bytesRead < destination.Length)
{
/// <summary>Unbuffered, reads a block of bytes from the file handle into the given buffer.</summary>
/// <param name="buffer">The buffer into which data from the file is read.</param>
/// <returns>
- /// The total number of bytes read into the buffer. This might be less than the number of bytes requested
+ /// The total number of bytes read into the buffer. This might be less than the number of bytes requested
/// if that number of bytes are not currently available, or zero if the end of the stream is reached.
/// </returns>
private unsafe int ReadNative(Span<byte> buffer)
_asyncState.Memory = destination;
return waitTask.ContinueWith((t, s) =>
{
- // The options available on Unix for writing asynchronously to an arbitrary file
- // handle typically amount to just using another thread to do the synchronous write,
+ // The options available on Unix for writing asynchronously to an arbitrary file
+ // handle typically amount to just using another thread to do the synchronous write,
// which is exactly what this implementation does. This does mean there are subtle
- // differences in certain FileStream behaviors between Windows and Unix when multiple
- // asynchronous operations are issued against the stream to execute concurrently; on
- // Unix the operations will be serialized due to the usage of a semaphore, but the
- // position /length information won't be updated until after the write has completed,
+ // differences in certain FileStream behaviors between Windows and Unix when multiple
+ // asynchronous operations are issued against the stream to execute concurrently; on
+ // Unix the operations will be serialized due to the usage of a semaphore, but the
+ // position /length information won't be updated until after the write has completed,
// whereas on Windows it may happen before the write has completed.
Debug.Assert(t.Status == TaskStatus.RanToCompletion);
_asyncState.ReadOnlyMemory = source;
return new ValueTask(waitTask.ContinueWith((t, s) =>
{
- // The options available on Unix for writing asynchronously to an arbitrary file
- // handle typically amount to just using another thread to do the synchronous write,
+ // The options available on Unix for writing asynchronously to an arbitrary file
+ // handle typically amount to just using another thread to do the synchronous write,
// which is exactly what this implementation does. This does mean there are subtle
- // differences in certain FileStream behaviors between Windows and Unix when multiple
- // asynchronous operations are issued against the stream to execute concurrently; on
- // Unix the operations will be serialized due to the usage of a semaphore, but the
- // position/length information won't be updated until after the write has completed,
+ // differences in certain FileStream behaviors between Windows and Unix when multiple
+ // asynchronous operations are issued against the stream to execute concurrently; on
+ // Unix the operations will be serialized due to the usage of a semaphore, but the
+ // position/length information won't be updated until after the write has completed,
// whereas on Windows it may happen before the write has completed.
Debug.Assert(t.Status == TaskStatus.RanToCompletion);
/// <summary>Sets the current position of this stream to the given value.</summary>
/// <param name="offset">The point relative to origin from which to begin seeking. </param>
/// <param name="origin">
- /// Specifies the beginning, the end, or the current position as a reference
+ /// Specifies the beginning, the end, or the current position as a reference
/// point for offset, using a value of type SeekOrigin.
/// </param>
/// <returns>The new position in the stream.</returns>
VerifyOSHandlePosition();
// Flush our write/read buffer. FlushWrite will output any write buffer we have and reset _bufferWritePos.
- // We don't call FlushRead, as that will do an unnecessary seek to rewind the read buffer, and since we're
- // about to seek and update our position, we can simply update the offset as necessary and reset our read
- // position and length to 0. (In the future, for some simple cases we could potentially add an optimization
+ // We don't call FlushRead, as that will do an unnecessary seek to rewind the read buffer, and since we're
+ // about to seek and update our position, we can simply update the offset as necessary and reset our read
+ // position and length to 0. (In the future, for some simple cases we could potentially add an optimization
// here to just move data around in the buffer for short jumps, to avoid re-reading the data from disk.)
FlushWriteBuffer();
if (origin == SeekOrigin.Current)
/// <summary>Sets the current position of this stream to the given value.</summary>
/// <param name="offset">The point relative to origin from which to begin seeking. </param>
/// <param name="origin">
- /// Specifies the beginning, the end, or the current position as a reference
+ /// Specifies the beginning, the end, or the current position as a reference
/// point for offset, using a value of type SeekOrigin.
/// </param>
/// <returns>The new position in the stream.</returns>
// If the handle is a pipe, ReadFile will block until there
// has been a write on the other end. We'll just have to deal with it,
- // For the read end of a pipe, you can mess up and
+ // For the read end of a pipe, you can mess up and
// accidentally read synchronously from an async pipe.
if ((access & FileAccess.Read) != 0)
{
*
* Also buffering is added into Win32FileStream as well. Folded in the
* code from BufferedStream, so all the comments about it being mostly
- * aggressive (and the possible perf improvement) apply to Win32FileStream as
+ * aggressive (and the possible perf improvement) apply to Win32FileStream as
* well. Also added some buffering to the async code paths.
*
* Class Invariants:
* should be true:
* 0 <= _readPos <= _readLen < _bufferSize
* 0 <= _writePos < _bufferSize
- * _readPos == _readLen && _readPos > 0 implies the read buffer is valid,
+ * _readPos == _readLen && _readPos > 0 implies the read buffer is valid,
* but we're at the end of the buffer.
* _readPos == _readLen == 0 means the read buffer contains garbage.
* Either _writePos can be greater than 0, or _readLen & _readPos can be
}
}
- // This is necessary for async IO using IO Completion ports via our
- // managed Threadpool API's. This (theoretically) calls the OS's
- // BindIoCompletionCallback method, and passes in a stub for the
+ // This is necessary for async IO using IO Completion ports via our
+ // managed Threadpool API's. This (theoretically) calls the OS's
+ // BindIoCompletionCallback method, and passes in a stub for the
// LPOVERLAPPED_COMPLETION_ROUTINE. This stub looks at the Overlapped
- // struct for this request and gets a delegate to a managed callback
+ // struct for this request and gets a delegate to a managed callback
// from there, which it then calls on a threadpool thread. (We allocate
// our native OVERLAPPED structs 2 pointers too large and store EE state
// & GC handles there, one to an IAsyncResult, the other to a delegate.)
_canSeek = handleType == Interop.Kernel32.FileTypes.FILE_TYPE_DISK;
_isPipe = handleType == Interop.Kernel32.FileTypes.FILE_TYPE_PIPE;
- // This is necessary for async IO using IO Completion ports via our
- // managed Threadpool API's. This calls the OS's
- // BindIoCompletionCallback method, and passes in a stub for the
+ // This is necessary for async IO using IO Completion ports via our
+ // managed Threadpool API's. This calls the OS's
+ // BindIoCompletionCallback method, and passes in a stub for the
// LPOVERLAPPED_COMPLETION_ROUTINE. This stub looks at the Overlapped
- // struct for this request and gets a delegate to a managed callback
+ // struct for this request and gets a delegate to a managed callback
// from there, which it then calls on a threadpool thread. (We allocate
- // our native OVERLAPPED structs 2 pointers too large and store EE
+ // our native OVERLAPPED structs 2 pointers too large and store EE
// state & a handle to a delegate there.)
- //
+ //
// If, however, we've already bound this file handle to our completion port,
// don't try to bind it again because it will fail. A handle can only be
// bound to a single completion port at a time.
protected override void Dispose(bool disposing)
{
- // Nothing will be done differently based on whether we are
+ // Nothing will be done differently based on whether we are
// disposing vs. finalizing. This is taking advantage of the
// weak ordering between normal finalizable objects & critical
- // finalizable objects, which I included in the SafeHandle
- // design for Win32FileStream, which would often "just work" when
+ // finalizable objects, which I included in the SafeHandle
+ // design for Win32FileStream, which would often "just work" when
// finalized.
try
{
if (_fileHandle != null && !_fileHandle.IsClosed && _writePos > 0)
{
- // Flush data to disk iff we were writing. After
+ // Flush data to disk iff we were writing. After
// thinking about this, we also don't need to flush
// our read position, regardless of whether the handle
- // was exposed to the user. They probably would NOT
+ // was exposed to the user. They probably would NOT
// want us to do this.
try
{
private void FlushWriteBufferForWriteByte() => FlushWriteBuffer();
- // Writes are buffered. Anytime the buffer fills up
+ // Writes are buffered. Anytime the buffer fills up
// (_writePos + delta > _bufferSize) or the buffer switches to reading
// and there is left over data (_writePos > 0), this function must be called.
private void FlushWriteBuffer(bool calledFromFinalizer = false)
Task writeTask = FlushWriteAsync(CancellationToken.None);
// With our Whidbey async IO & overlapped support for AD unloads,
// we don't strictly need to block here to release resources
- // since that support takes care of the pinning & freeing the
+ // since that support takes care of the pinning & freeing the
// overlapped struct. We need to do this when called from
// Close so that the handle is closed when Close returns, but
- // we don't need to call EndWrite from the finalizer.
- // Additionally, if we do call EndWrite, we block forever
- // because AD unloads prevent us from running the managed
- // callback from the IO completion port. Blocking here when
- // called from the finalizer during AD unload is clearly wrong,
- // but we can't use any sort of test for whether the AD is
- // unloading because if we weren't unloading, an AD unload
+ // we don't need to call EndWrite from the finalizer.
+ // Additionally, if we do call EndWrite, we block forever
+ // because AD unloads prevent us from running the managed
+ // callback from the IO completion port. Blocking here when
+ // called from the finalizer during AD unload is clearly wrong,
+ // but we can't use any sort of test for whether the AD is
+ // unloading because if we weren't unloading, an AD unload
// could happen on a separate thread before we call EndWrite.
if (!calledFromFinalizer)
{
new ReadOnlySpan<byte>(GetBuffer(), _readPos, n).CopyTo(destination);
_readPos += n;
- // We may have read less than the number of bytes the user asked
+ // We may have read less than the number of bytes the user asked
// for, but that is part of the Stream contract. Reading again for
- // more data may cause us to block if we're using a device with
+ // more data may cause us to block if we're using a device with
// no clear end of file, such as a serial port or pipe. If we
// blocked here & this code was used with redirected pipes for a
// process's standard output, this can lead to deadlocks involving
// two processes. But leave this here for files to avoid what would
- // probably be a breaking change. --
+ // probably be a breaking change. --
- // If we are reading from a device with no clear EOF like a
+ // If we are reading from a device with no clear EOF like a
// serial port or a pipe, this will cause us to block incorrectly.
if (!_isPipe)
{
// If we hit the end of the buffer and didn't have enough bytes, we must
// read some more from the underlying stream. However, if we got
- // fewer bytes from the underlying stream than we asked for (i.e. we're
+ // fewer bytes from the underlying stream than we asked for (i.e. we're
// probably blocked), don't ask for more bytes.
if (n < destination.Length && !isBlocked)
{
Debug.Assert(_readPos == _readLength, "Read buffer should be empty!");
int moreBytesRead = ReadNative(destination.Slice(n));
n += moreBytesRead;
- // We've just made our buffer inconsistent with our position
+ // We've just made our buffer inconsistent with our position
// pointer. We must throw away the read buffer.
_readPos = 0;
_readLength = 0;
}
// We now must update the read buffer. We can in some cases simply
- // update _readPos within the buffer, copy around the buffer so our
- // Position property is still correct, and avoid having to do more
+ // update _readPos within the buffer, copy around the buffer so our
+ // Position property is still correct, and avoid having to do more
// reads from the disk. Otherwise, discard the buffer's contents.
if (_readLength > 0)
{
_readLength -= _readPos;
_readPos = 0;
}
- // If we still have buffered data, we must update the stream's
+ // If we still have buffered data, we must update the stream's
// position so our Position property is correct.
if (_readLength > 0)
SeekCore(_fileHandle, _readLength, SeekOrigin.Current);
}
// This doesn't do argument checking. Necessary for SetLength, which must
- // set the file pointer beyond the end of the file. This will update the
+ // set the file pointer beyond the end of the file. This will update the
// internal position
private long SeekCore(SafeFileHandle fileHandle, long offset, SeekOrigin origin, bool closeInvalidHandle = false)
{
// the buffer to disk and copy any remaining data into our buffer.
// The assumption here is memcpy is cheaper than disk (or net) IO.
// (10 milliseconds to disk vs. ~20-30 microseconds for a 4K memcpy)
- // So the extra copying will reduce the total number of writes, in
- // non-pathological cases (i.e. write 1 byte, then write for the buffer
+ // So the extra copying will reduce the total number of writes, in
+ // non-pathological cases (i.e. write 1 byte, then write for the buffer
// size repeatedly)
if (_writePos > 0)
{
else
{
// ERROR_INVALID_PARAMETER may be returned for writes
- // where the position is too large or for synchronous writes
+ // where the position is too large or for synchronous writes
// to a handle opened asynchronously.
if (errorCode == ERROR_INVALID_PARAMETER)
throw new IOException(SR.IO_FileTooLongOrHandleNotSync);
// & stderr with the Process class, it's easy to deadlock your
// parent & child processes when doing writes 4K at a time. The
// OS appears to use a 4K buffer internally. If you write to a
- // pipe that is full, you will block until someone read from
- // that pipe. If you try reading from an empty pipe and
- // Win32FileStream's ReadAsync blocks waiting for data to fill it's
+ // pipe that is full, you will block until someone read from
+ // that pipe. If you try reading from an empty pipe and
+ // Win32FileStream's ReadAsync blocks waiting for data to fill it's
// internal buffer, you will be blocked. In a case where a child
// process writes to stdout & stderr while a parent process tries
// reading from both, you can easily get into a deadlock here.
// To avoid this deadlock, don't buffer when doing async IO on
- // pipes. But don't completely ignore buffered data either.
+ // pipes. But don't completely ignore buffered data either.
if (_readPos < _readLength)
{
int n = Math.Min(_readLength - _readPos, destination.Length);
if (_writePos > 0) FlushWriteBuffer();
if (_readPos == _readLength)
{
- // I can't see how to handle buffering of async requests when
+ // I can't see how to handle buffering of async requests when
// filling the buffer asynchronously, without a lot of complexity.
- // The problems I see are issuing an async read, we do an async
- // read to fill the buffer, then someone issues another read
- // (either synchronously or asynchronously) before the first one
+ // The problems I see are issuing an async read, we do an async
+ // read to fill the buffer, then someone issues another read
+ // (either synchronously or asynchronously) before the first one
// returns. This would involve some sort of complex buffer locking
// that we probably don't want to get into, at least not in V1.
// If we did a sync read to fill the buffer, we could avoid the
// problem, and any async read less than 64K gets turned into a
- // synchronous read by NT anyways... --
+ // synchronous read by NT anyways... --
if (destination.Length < _bufferLength)
{
{
// For streams with no clear EOF like serial ports or pipes
// we cannot read more data without causing an app to block
- // incorrectly. Pipes don't go down this path
+ // incorrectly. Pipes don't go down this path
// though. This code needs to be fixed.
// Throw away read buffer.
_readPos = 0;
intOverlapped->OffsetLow = unchecked((int)_filePosition);
intOverlapped->OffsetHigh = (int)(_filePosition >> 32);
- // When using overlapped IO, the OS is not supposed to
- // touch the file pointer location at all. We will adjust it
+ // When using overlapped IO, the OS is not supposed to
+ // touch the file pointer location at all. We will adjust it
// ourselves. This isn't threadsafe.
// WriteFile should not update the file pointer when writing
- // in overlapped mode, according to MSDN. But it does update
- // the file pointer when writing to a UNC path!
- // So changed the code below to seek to an absolute
+ // in overlapped mode, according to MSDN. But it does update
+ // the file pointer when writing to a UNC path!
+ // So changed the code below to seek to an absolute
// location, not a relative one. ReadFile seems consistent though.
SeekCore(_fileHandle, destination.Length, SeekOrigin.Current);
}
// on async requests that completed sequentially, r==0
// You will NEVER RELIABLY be able to get the number of bytes
// read back from this call when using overlapped structures! You must
- // not pass in a non-null lpNumBytesRead to ReadFile when using
+ // not pass in a non-null lpNumBytesRead to ReadFile when using
// overlapped structures! This is by design NT behavior.
if (r == -1)
{
// For pipes, when they hit EOF, they will come here.
if (errorCode == ERROR_BROKEN_PIPE)
{
- // Not an error, but EOF. AsyncFSCallback will NOT be
+ // Not an error, but EOF. AsyncFSCallback will NOT be
// called. Call the user callback here.
// We clear the overlapped status bit for this special case.
}
else
{
- // Due to a workaround for a race condition in NT's ReadFile &
+ // Due to a workaround for a race condition in NT's ReadFile &
// WriteFile routines, we will always be returning 0 from ReadFileNative
- // when we do async IO instead of the number of bytes read,
- // irregardless of whether the operation completed
+ // when we do async IO instead of the number of bytes read,
+ // irregardless of whether the operation completed
// synchronously or asynchronously. We absolutely must not
// set asyncResult._numBytes here, since will never have correct
- // results.
+ // results.
}
return completionSource.Task;
// byte[] sizes that are powers of 2 and thus fit nicely into our buffer, which is
// also a power of 2. If after our write the buffer still has remaining space,
// then we're done and can return a completed task now. But if we filled the buffer
- // completely, we want to do the asynchronous flush/write as part of this operation
+ // completely, we want to do the asynchronous flush/write as part of this operation
// rather than waiting until the next write that fills the buffer.
if (source.Length != remainingBuffer)
return default;
flushTask = FlushWriteAsync(cancellationToken);
// If we already copied all of the data into the buffer,
- // simply return the flush task here. Same goes for if the task has
+ // simply return the flush task here. Same goes for if the task has
// already completed and was unsuccessful.
if (writeDataStoredInBuffer ||
flushTask.IsFaulted ||
intOverlapped->OffsetLow = (int)_filePosition;
intOverlapped->OffsetHigh = (int)(_filePosition >> 32);
- // When using overlapped IO, the OS is not supposed to
- // touch the file pointer location at all. We will adjust it
+ // When using overlapped IO, the OS is not supposed to
+ // touch the file pointer location at all. We will adjust it
// ourselves. This isn't threadsafe.
SeekCore(_fileHandle, source.Length, SeekOrigin.Current);
}
// On async requests that completed sequentially, r==0
// You will NEVER RELIABLY be able to get the number of bytes
// written back from this call when using overlapped IO! You must
- // not pass in a non-null lpNumBytesWritten to WriteFile when using
+ // not pass in a non-null lpNumBytesWritten to WriteFile when using
// overlapped structures! This is ByDesign NT behavior.
if (r == -1)
{
}
else
{
- // Due to a workaround for a race condition in NT's ReadFile &
+ // Due to a workaround for a race condition in NT's ReadFile &
// WriteFile routines, we will always be returning 0 from WriteFileNative
- // when we do async IO instead of the number of bytes written,
- // irregardless of whether the operation completed
+ // when we do async IO instead of the number of bytes written,
+ // irregardless of whether the operation completed
// synchronously or asynchronously. We absolutely must not
// set asyncResult._numBytes here, since will never have correct
- // results.
+ // results.
}
return completionSource.Task;
private const int ERROR_INVALID_PARAMETER = 87;
private const int ERROR_IO_PENDING = 997;
- // __ConsoleStream also uses this code.
+ // __ConsoleStream also uses this code.
private unsafe int ReadFileNative(SafeFileHandle handle, Span<byte> bytes, NativeOverlapped* overlapped, out int errorCode)
{
Debug.Assert(handle != null, "handle != null");
throw Error.GetFileNotOpen();
// TODO: https://github.com/dotnet/corefx/issues/32837 (stop doing this synchronous work!!).
- // The always synchronous data transfer between the OS and the internal buffer is intentional
+ // The always synchronous data transfer between the OS and the internal buffer is intentional
// because this is needed to allow concurrent async IO requests. Concurrent data transfer
// between the OS and the internal buffer will result in race conditions. Since FlushWrite and
- // FlushRead modify internal state of the stream and transfer data between the OS and the
+ // FlushRead modify internal state of the stream and transfer data between the OS and the
// internal buffer, they cannot be truly async. We will, however, flush the OS file buffers
- // asynchronously because it doesn't modify any internal state of the stream and is potentially
+ // asynchronously because it doesn't modify any internal state of the stream and is potentially
// a long running process.
try
{
/// <summary>
/// Whether asynchronous read/write/flush operations should be performed using async I/O.
- /// On Windows FileOptions.Asynchronous controls how the file handle is configured,
- /// and then as a result how operations are issued against that file handle. On Unix,
- /// there isn't any distinction around how file descriptors are created for async vs
+ /// On Windows FileOptions.Asynchronous controls how the file handle is configured,
+ /// and then as a result how operations are issued against that file handle. On Unix,
+ /// there isn't any distinction around how file descriptors are created for async vs
/// sync, but we still differentiate how the operations are issued in order to provide
/// similar behavioral semantics and performance characteristics as on Windows. On
/// Windows, if non-async, async read/write requests just delegate to the base stream,
public override Task FlushAsync(CancellationToken cancellationToken)
{
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Flush() which a subclass might have overridden. To be safe
+ // since it does not call through to Flush() which a subclass might have overridden. To be safe
// we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Flush) when we are not sure.
if (GetType() != typeof(FileStream))
}
else
{
- // This type is derived from FileStream and/or the stream is in async mode. If this is a
+ // This type is derived from FileStream and/or the stream is in async mode. If this is a
// derived type, it may have overridden Read(byte[], int, int) prior to this Read(Span<byte>)
// overload being introduced. In that case, this Read(Span<byte>) overload should use the behavior
// of Read(byte[],int,int) overload. Or if the stream is in async mode, we can't call the
throw new ArgumentException(SR.Argument_InvalidOffLen /*, no good single parameter name to pass*/);
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Read() which a subclass might have overridden.
+ // since it does not call through to Read() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Read/ReadAsync) when we are not sure.
// Similarly, if we weren't opened for asynchronous I/O, call to the base implementation so that
}
else
{
- // This type is derived from FileStream and/or the stream is in async mode. If this is a
+ // This type is derived from FileStream and/or the stream is in async mode. If this is a
// derived type, it may have overridden Write(byte[], int, int) prior to this Write(ReadOnlySpan<byte>)
// overload being introduced. In that case, this Write(ReadOnlySpan<byte>) overload should use the behavior
// of Write(byte[],int,int) overload. Or if the stream is in async mode, we can't call the
throw new ArgumentException(SR.Argument_InvalidOffLen /*, no good single parameter name to pass*/);
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Write() or WriteAsync() which a subclass might have overridden.
+ // since it does not call through to Write() or WriteAsync() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Write/WriteAsync) when we are not sure.
if (!_useAsyncIO || GetType() != typeof(FileStream))
}
/// <summary>
- /// Clears buffers for this stream, and if <param name="flushToDisk"/> is true,
+ /// Clears buffers for this stream, and if <param name="flushToDisk"/> is true,
/// causes any buffered data to be written to the file.
/// </summary>
public virtual void Flush(bool flushToDisk)
long curPos = SeekCore(_fileHandle, 0, SeekOrigin.Current);
if (oldPos != curPos)
{
- // For reads, this is non-fatal but we still could have returned corrupted
- // data in some cases, so discard the internal buffer. For writes,
+ // For reads, this is non-fatal but we still could have returned corrupted
+ // data in some cases, so discard the internal buffer. For writes,
// this is a problem; discard the buffer and error out.
_readPos = _readLength = 0;
if (_writePos > 0)
// FileLoadException
// FileNotFoundException
// PathTooLongException
- // PipeException
+ // PipeException
e is IOException ||
// Note that SecurityException is only thrown on runtimes that support CAS
- // e is SecurityException ||
+ // e is SecurityException ||
e is UnauthorizedAccessException ||
e is NotSupportedException ||
(e is ArgumentException && !(e is ArgumentNullException));
/// <summary>
- /// Gets the array used for buffering reading and writing.
+ /// Gets the array used for buffering reading and writing.
/// If the array hasn't been allocated, this will lazily allocate it.
/// </summary>
/// <returns>The buffer.</returns>
/// <summary>
/// Flushes the internal read/write buffer for this stream. If write data has been buffered,
- /// that data is written out to the underlying file. Or if data has been buffered for
- /// reading from the stream, the data is dumped and our position in the underlying file
+ /// that data is written out to the underlying file. Or if data has been buffered for
+ /// reading from the stream, the data is dumped and our position in the underlying file
/// is rewound as necessary. This does not flush the OS buffer.
/// </summary>
private void FlushInternalBuffer()
{
// Reading is done by blocks from the file, but someone could read
// 1 byte from the buffer then write. At that point, the OS's file
- // pointer is out of sync with the stream's position. All write
+ // pointer is out of sync with the stream's position. All write
// functions should call this function to preserve the position in the file.
AssertBufferInvariants();
throw Error.GetFileNotOpen();
// Make sure we're good to write. We only need to do this if there's nothing already
- // in our write buffer, since if there is something in the buffer, we've already done
+ // in our write buffer, since if there is something in the buffer, we've already done
// this checking and flushing.
if (_writePos == 0)
{
~FileStream()
{
- // Preserved for compatibility since FileStream has defined a
+ // Preserved for compatibility since FileStream has defined a
// finalizer in past releases and derived classes may depend
// on Dispose(false) call.
Dispose(false);
// buffer is used) and where operations on the FileStream are not being performed concurrently.
Debug.Assert(bytes == null || ReferenceEquals(bytes, _stream._buffer));
- // The _preallocatedOverlapped is null if the internal buffer was never created, so we check for
+ // The _preallocatedOverlapped is null if the internal buffer was never created, so we check for
// a non-null bytes before using the stream's _preallocatedOverlapped
_overlapped = bytes != null && _stream.CompareExchangeCurrentOverlappedOwner(this, null) == null ?
_stream._fileHandle.ThreadPoolBinding!.AllocateNativeOverlapped(_stream._preallocatedOverlapped!) : // allocated when buffer was created, and buffer is non-null
}
// Ensure we're no longer set as the current completion source (we may not have been to begin with).
- // Only one operation at a time is eligible to use the preallocated overlapped,
+ // Only one operation at a time is eligible to use the preallocated overlapped,
_stream.CompareExchangeCurrentOverlappedOwner(null, this);
}
- // When doing IO asynchronously (i.e. _isAsync==true), this callback is
- // called by a free thread in the threadpool when the IO operation
- // completes.
+ // When doing IO asynchronously (i.e. _isAsync==true), this callback is
+ // called by a free thread in the threadpool when the IO operation
+ // completes.
internal static unsafe void IOCallback(uint errorCode, uint numBytes, NativeOverlapped* pOverlapped)
{
// Extract the completion source from the overlapped. The state in the overlapped
Debug.Assert(completionSource._overlapped == pOverlapped, "Overlaps don't match");
// Handle reading from & writing to closed pipes. While I'm not sure
- // this is entirely necessary anymore, maybe it's possible for
- // an async read on a pipe to be issued and then the pipe is closed,
+ // this is entirely necessary anymore, maybe it's possible for
+ // an async read on a pipe to be issued and then the pipe is closed,
// returning this error. This may very well be necessary.
ulong packedResult;
if (errorCode != 0 && errorCode != ERROR_BROKEN_PIPE && errorCode != ERROR_NO_DATA)
namespace System.IO
{
// A MemoryStream represents a Stream in memory (ie, it has no backing store).
- // This stream may reduce the need for temporary buffers and files in
- // an application.
- //
+ // This stream may reduce the need for temporary buffers and files in
+ // an application.
+ //
// There are two ways to create a MemoryStream. You can initialize one
- // from an unsigned byte array, or you can create an empty one. Empty
+ // from an unsigned byte array, or you can create an empty one. Empty
// memory streams are resizable, while ones created with a byte array provide
// a stream "view" of the data.
public class MemoryStream : Stream
int origPos = _position;
int newPos = origPos + count;
-
+
if ((uint)newPos > (uint)_length)
{
_position = _length;
// Gets & sets the capacity (number of bytes allocated) for this stream.
// The capacity cannot be set to a value less than the current length
// of the stream.
- //
+ //
public virtual int Capacity
{
get
StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Read() which a subclass might have overridden.
+ // since it does not call through to Read() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Read) when we are not sure.
if (GetType() != typeof(MemoryStream))
StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to ReadAsync() which a subclass might have overridden.
+ // since it does not call through to ReadAsync() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into ReadAsync) when we are not sure.
if (GetType() != typeof(MemoryStream))
// value must be nonnegative and less than the space remaining in
// the array, int.MaxValue - origin
// Origin is 0 in all cases other than a MemoryStream created on
- // top of an existing array and a specific starting offset was passed
- // into the MemoryStream constructor. The upper bounds prevents any
- // situations where a stream may be created on top of an array then
- // the stream is made longer than the maximum possible length of the
+ // top of an existing array and a specific starting offset was passed
+ // into the MemoryStream constructor. The upper bounds prevents any
+ // situations where a stream may be created on top of an array then
+ // the stream is made longer than the maximum possible length of the
// array (int.MaxValue).
- //
+ //
public override void SetLength(long value)
{
if (value < 0 || value > int.MaxValue)
public static char[] GetInvalidPathChars() => new char[] { '\0' };
- // Expands the given path to a fully qualified path.
+ // Expands the given path to a fully qualified path.
public static string GetFullPath(string path)
{
if (path == null)
throw new ArgumentException(SR.Arg_PathEmpty, nameof(path));
if (path.Contains('\0'))
- throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path));
-
+ throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path));
+
// Expand with current directory if necessary
if (!IsPathRooted(path))
{
#endif
{
// Provides methods for processing file system strings in a cross-platform manner.
- // Most of the methods don't do a complete parsing (such as examining a UNC hostname),
+ // Most of the methods don't do a complete parsing (such as examining a UNC hostname),
// but they will handle most string operations.
public static partial class Path
{
/// <summary>
/// Returns the extension of the given path.
/// </summary>
- /// <remarks>
+ /// <remarks>
/// The returned value is an empty ReadOnlySpan if the given path does not include an extension.
/// </remarks>
public static ReadOnlySpan<char> GetExtension(ReadOnlySpan<char> path)
{
return string.Empty;
}
-
+
int maxSize = 0;
foreach (string? path in paths)
{
/// <summary>
/// Returns true if the path is effectively empty for the current OS.
- /// For unix, this is empty or null. For Windows, this is empty, null, or
+ /// For unix, this is empty or null. For Windows, this is empty, null, or
/// just spaces ((char)32).
/// </summary>
internal static bool IsEffectivelyEmpty(string? path)
/// <summary>
/// Normalize separators in the given path. Converts forward slashes into back slashes and compresses slash runs, keeping initial 2 if present.
/// Also trims initial whitespace in front of "rooted" paths (see PathStartSkip).
- ///
+ ///
/// This effectively replicates the behavior of the legacy NormalizePath when it was called with fullCheck=false and expandShortpaths=false.
/// The current NormalizePath gets directory separator normalization from Win32's GetFullPathName(), which will resolve relative paths and as
/// such can't be used here (and is overkill for our uses).
- ///
+ ///
/// Like the current NormalizePath this will not try and analyze periods/spaces within directory segments.
/// </summary>
/// <remarks>
/// The only callers that used to use Path.Normalize(fullCheck=false) were Path.GetDirectoryName() and Path.GetPathRoot(). Both usages do
/// not need trimming of trailing whitespace here.
- ///
+ ///
/// GetPathRoot() could technically skip normalizing separators after the second segment- consider as a future optimization.
- ///
+ ///
/// For legacy desktop behavior with ExpandShortPaths:
/// - It has no impact on GetPathRoot() so doesn't need consideration.
/// - It could impact GetDirectoryName(), but only if the path isn't relative (C:\ or \\Server\Share).
- ///
+ ///
/// In the case of GetDirectoryName() the ExpandShortPaths behavior was undocumented and provided inconsistent results if the path was
/// fixed/relative. For example: "C:\PROGRA~1\A.TXT" would return "C:\Program Files" while ".\PROGRA~1\A.TXT" would return ".\PROGRA~1". If you
/// ultimately call GetFullPath() this doesn't matter, but if you don't or have any intermediate string handling could easily be tripped up by
/// this undocumented behavior.
- ///
+ ///
/// We won't match this old behavior because:
- ///
+ ///
/// 1. It was undocumented
/// 2. It was costly (extremely so if it actually contained '~')
/// 3. Doesn't play nice with string logic
/// <summary>
/// Returns true if the path is effectively empty for the current OS.
- /// For unix, this is empty or null. For Windows, this is empty, null, or
+ /// For unix, this is empty or null. For Windows, this is empty, null, or
/// just spaces ((char)32).
/// </summary>
internal static bool IsEffectivelyEmpty(ReadOnlySpan<char> path)
if (PathInternal.IsDirectorySeparator(path[skip - 1]))
skip--;
- // Remove "//", "/./", and "/../" from the path by copying each character to the output,
- // except the ones we're removing, such that the builder contains the normalized path
+ // Remove "//", "/./", and "/../" from the path by copying each character to the output,
+ // except the ones we're removing, such that the builder contains the normalized path
// at the end.
if (skip > 0)
{
if (!string.IsNullOrEmpty(userHomeDirectory))
return userHomeDirectory;
- // In initialization conditions, however, the "HOME" environment variable may
+ // In initialization conditions, however, the "HOME" environment variable may
// not yet be set. For such cases, consult with the password entry.
unsafe
{
// First try with a buffer that should suffice for 99% of cases.
- // Note that, theoretically, userHomeDirectory may be null in the success case
+ // Note that, theoretically, userHomeDirectory may be null in the success case
// if we simply couldn't find a home directory for the current user.
// In that case, we pass back the null value and let the caller decide
// what to do.
var errorInfo = new Interop.ErrorInfo(error);
- // If the call failed because the buffer was too small, return false to
+ // If the call failed because the buffer was too small, return false to
// indicate the caller should try again with a larger buffer.
if (errorInfo.Error == Interop.Error.ERANGE)
{
/*============================================================
**
-**
-**
**
**
-** Purpose: Pins a byte[], exposing it as an unmanaged memory
+**
+**
+** Purpose: Pins a byte[], exposing it as an unmanaged memory
** stream. Used in ResourceReader for corner cases.
**
**
/*============================================================
**
-**
-**
+**
+**
**
**
** Purpose: Abstract base class for all Streams. Provides
// Stream used to require that all cleanup logic went into Close(),
// which was thought up before we invented IDisposable. However, we
- // need to follow the IDisposable pattern so that users can write
- // sensible subclasses without needing to inspect all their base
+ // need to follow the IDisposable pattern so that users can write
+ // sensible subclasses without needing to inspect all their base
// classes, and without worrying about version brittleness, from a
// base class switching to the Dispose pattern. We're moving
- // Stream to the Dispose(bool) pattern - that's where all subclasses
+ // Stream to the Dispose(bool) pattern - that's where all subclasses
// should put their cleanup now.
public virtual void Close()
{
protected virtual void Dispose(bool disposing)
{
// Note: Never change this to call other virtual methods on Stream
- // like Write, since the state on subclasses has already been
+ // like Write, since the state on subclasses has already been
// torn down. This is the last code to run on cleanup for a stream.
}
{
if (!CanRead) throw Error.GetReadNotSupported();
- // To avoid a race with a stream's position pointer & generating race conditions
- // with internal buffer indexes in our own streams that
- // don't natively support async IO operations when there are multiple
+ // To avoid a race with a stream's position pointer & generating race conditions
+ // with internal buffer indexes in our own streams that
+ // don't natively support async IO operations when there are multiple
// async requests outstanding, we will block the application's main
// thread if it does a second IO request until the first one completes.
var semaphore = EnsureAsyncActiveSemaphoreInitialized();
{
if (!CanWrite) throw Error.GetWriteNotSupported();
- // To avoid a race condition with a stream's position pointer & generating conditions
- // with internal buffer indexes in our own streams that
- // don't natively support async IO operations when there are multiple
+ // To avoid a race condition with a stream's position pointer & generating conditions
+ // with internal buffer indexes in our own streams that
+ // don't natively support async IO operations when there are multiple
// async requests outstanding, we will block the application's main
// thread if it does a second IO request until the first one completes.
var semaphore = EnsureAsyncActiveSemaphoreInitialized();
finally { ArrayPool<byte>.Shared.Return(sharedBuffer); }
}
- // Reads one byte from the stream by calling Read(byte[], int, int).
+ // Reads one byte from the stream by calling Read(byte[], int, int).
// Will return an unsigned byte cast to an int or -1 on end of stream.
// This implementation does not perform well because it allocates a new
- // byte[] each time you call it, and should be overridden by any
+ // byte[] each time you call it, and should be overridden by any
// subclass that maintains an internal buffer. Then, it can help perf
// significantly for people who are reading one byte at a time.
public virtual int ReadByte()
// Writes one byte from the stream by calling Write(byte[], int, int).
// This implementation does not perform well because it allocates a new
- // byte[] each time you call it, and should be overridden by any
+ // byte[] each time you call it, and should be overridden by any
// subclass that maintains an internal buffer. Then, it can help perf
// significantly for people who are writing one byte at a time.
public virtual void WriteByte(byte value)
internal IAsyncResult BlockingBeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object? state)
{
// To avoid a race with a stream's position pointer & generating conditions
- // with internal buffer indexes in our own streams that
- // don't natively support async IO operations when there are multiple
+ // with internal buffer indexes in our own streams that
+ // don't natively support async IO operations when there are multiple
// async requests outstanding, we will block the application's main
- // thread and do the IO synchronously.
+ // thread and do the IO synchronously.
// This can't perform well - use a different approach.
SynchronousAsyncResult asyncResult;
try
internal IAsyncResult BlockingBeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object? state)
{
- // To avoid a race condition with a stream's position pointer & generating conditions
- // with internal buffer indexes in our own streams that
- // don't natively support async IO operations when there are multiple
+ // To avoid a race condition with a stream's position pointer & generating conditions
+ // with internal buffer indexes in our own streams that
+ // don't natively support async IO operations when there are multiple
// async requests outstanding, we will block the application's main
- // thread and do the IO synchronously.
+ // thread and do the IO synchronously.
// This can't perform well - use a different approach.
SynchronousAsyncResult asyncResult;
try
} // class SynchronousAsyncResult
- // SyncStream is a wrapper around a stream that takes
+ // SyncStream is a wrapper around a stream that takes
// a lock for every operation making it thread safe.
private sealed class SyncStream : Stream, IDisposable
{
}
}
- // In the off chance that some wrapped stream has different
+ // In the off chance that some wrapped stream has different
// semantics for Close vs. Dispose, let's preserve that.
public override void Close()
{
namespace System.IO
{
// This class implements a TextReader for reading characters to a Stream.
- // This is designed for character input in a particular Encoding,
- // whereas the Stream class is designed for byte input and output.
+ // This is designed for character input in a particular Encoding,
+ // whereas the Stream class is designed for byte input and output.
public class StreamReader : TextReader
{
// StreamReader.Null is threadsafe.
// Using a 1K byte buffer and a 4K FileStream buffer works out pretty well
// perf-wise. On even a 40 MB text file, any perf loss by using a 4K
- // buffer is negated by the win of allocating a smaller byte[], which
+ // buffer is negated by the win of allocating a smaller byte[], which
// saves construction time. This does break adaptive buffering,
// but this is slightly faster.
private const int DefaultBufferSize = 1024; // Byte buffer size
// This is used only for preamble detection
private int _bytePos;
- // This is the maximum number of chars we can get from one call to
+ // This is the maximum number of chars we can get from one call to
// ReadBuffer. Used so ReadBuffer can tell when to copy data into
// a user's char[] directly, instead of our internal char[].
private int _maxCharsPerBuffer;
// We will support looking for byte order marks in the stream and trying
// to decide what the encoding might be from the byte order marks, IF they
- // exist. But that's all we'll do.
+ // exist. But that's all we'll do.
private bool _detectEncoding;
// Whether we must still check for the encoding's given preamble at the
// beginning of this file.
private bool _checkPreamble;
- // Whether the stream is most likely not going to give us back as much
+ // Whether the stream is most likely not going to give us back as much
// data as we want the next time we call it. We must do the computation
// before we do any byte order mark handling and save the result. Note
- // that we need this to allow users to handle streams used for an
- // interactive protocol, where they block waiting for the remote end
+ // that we need this to allow users to handle streams used for an
+ // interactive protocol, where they block waiting for the remote end
// to send a response, like logging in on a Unix machine.
private bool _isBlocked;
- // The intent of this field is to leave open the underlying stream when
- // disposing of this StreamReader. A name like _leaveOpen is better,
+ // The intent of this field is to leave open the underlying stream when
+ // disposing of this StreamReader. A name like _leaveOpen is better,
// but this type is serializable, and this field's name was _closable.
private bool _closable; // Whether to close the underlying stream.
- // We don't guarantee thread safety on StreamReader, but we should at
+ // We don't guarantee thread safety on StreamReader, but we should at
// least prevent users from trying to read anything while an Async
// read from the same thread is in progress.
private Task _asyncReadTask = Task.CompletedTask;
private void CheckAsyncTaskInProgress()
{
- // We are not locking the access to _asyncReadTask because this is not meant to guarantee thread safety.
+ // We are not locking the access to _asyncReadTask because this is not meant to guarantee thread safety.
// We are simply trying to deter calling any Read APIs while an async Read from the same thread is in progress.
if (!_asyncReadTask.IsCompleted)
{
private static void ThrowAsyncIOInProgress() =>
throw new InvalidOperationException(SR.InvalidOperation_AsyncIOInProgress);
- // StreamReader by default will ignore illegal UTF8 characters. We don't want to
- // throw here because we want to be able to read ill-formed data without choking.
- // The high level goal is to be tolerant of encoding errors when we read and very strict
- // when we write. Hence, default StreamWriter encoding will throw on error.
+ // StreamReader by default will ignore illegal UTF8 characters. We don't want to
+ // throw here because we want to be able to read ill-formed data without choking.
+ // The high level goal is to be tolerant of encoding errors when we read and very strict
+ // when we write. Hence, default StreamWriter encoding will throw on error.
private StreamReader()
{
{
}
- // Creates a new StreamReader for the given stream. The
- // character encoding is set by encoding and the buffer size,
- // in number of 16-bit characters, is set by bufferSize.
- //
+ // Creates a new StreamReader for the given stream. The
+ // character encoding is set by encoding and the buffer size,
+ // in number of 16-bit characters, is set by bufferSize.
+ //
// Note that detectEncodingFromByteOrderMarks is a very
// loose attempt at detecting the encoding by looking at the first
// 3 bytes of the stream. It will recognize UTF-8, little endian
// unicode, and big endian unicode text, but that's it. If neither
// of those three match, it will use the Encoding you provided.
- //
+ //
public StreamReader(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize)
: this(stream, encoding, detectEncodingFromByteOrderMarks, bufferSize, false)
{
{
try
{
- // Note that Stream.Close() can potentially throw here. So we need to
- // ensure cleaning up internal resources, inside the finally block.
+ // Note that Stream.Close() can potentially throw here. So we need to
+ // ensure cleaning up internal resources, inside the finally block.
if (disposing)
{
_stream.Close();
// underlying stream to a known location then wants the StreamReader
// to start reading from this new point. This method should be called
// very sparingly, if ever, since it can lead to very poor performance.
- // However, it may be the only way of handling some scenarios where
+ // However, it may be the only way of handling some scenarios where
// users need to re-read the contents of a StreamReader a second time.
public void DiscardBufferedData()
{
_charLen = 0;
_charPos = 0;
// in general we'd like to have an invariant that encoding isn't null. However,
- // for startup improvements for NullStreamReader, we want to delay load encoding.
+ // for startup improvements for NullStreamReader, we want to delay load encoding.
if (_encoding != null)
{
_decoder = _encoding.GetDecoder();
public override int Read(Span<char> buffer) =>
GetType() == typeof(StreamReader) ? ReadSpan(buffer) :
base.Read(buffer); // Defer to Read(char[], ...) if a derived type may have previously overridden it
-
+
private int ReadSpan(Span<char> buffer)
{
ThrowIfDisposed();
CheckAsyncTaskInProgress();
int charsRead = 0;
- // As a perf optimization, if we had exactly one buffer's worth of
+ // As a perf optimization, if we had exactly one buffer's worth of
// data read in, let's try writing directly to the user's buffer.
bool readToUserBuffer = false;
int count = buffer.Length;
// Trims the preamble bytes from the byteBuffer. This routine can be called multiple times
// and we will buffer the bytes read until the preamble is matched or we determine that
- // there is no match. If there is no match, every byte read previously will be available
- // for further consumption. If there is a match, we will compress the buffer for the
+ // there is no match. If there is no match, every byte read previously will be available
+ // for further consumption. If there is a match, we will compress the buffer for the
// leading preamble bytes
private bool IsPreamble()
{
if (len == 0)
{
- // EOF but we might have buffered bytes from previous
+ // EOF but we might have buffered bytes from previous
// attempt to detect preamble that needs to be decoded now
if (_byteLen > 0)
{
}
// _isBlocked == whether we read fewer bytes than we asked for.
- // Note we must check it here because CompressBuffer or
+ // Note we must check it here because CompressBuffer or
// DetectEncoding will change byteLen.
_isBlocked = (_byteLen < _byteBuffer.Length);
}
- // This version has a perf optimization to decode data DIRECTLY into the
+ // This version has a perf optimization to decode data DIRECTLY into the
// user's buffer, bypassing StreamReader's own buffer.
// This gives a > 20% perf improvement for our encodings across the board,
// but only when asking for at least the number of characters that one
// buffer's worth of bytes could produce.
- // This optimization, if run, will break SwitchEncoding, so we must not do
- // this on the first call to ReadBuffer.
+ // This optimization, if run, will break SwitchEncoding, so we must not do
+ // this on the first call to ReadBuffer.
private int ReadBuffer(Span<char> userBuffer, out bool readToUserBuffer)
{
_charLen = 0;
int charsRead = 0;
// As a perf optimization, we can decode characters DIRECTLY into a
- // user's char[]. We absolutely must not write more characters
- // into the user's buffer than they asked for. Calculating
- // encoding.GetMaxCharCount(byteLen) each time is potentially very
- // expensive - instead, cache the number of chars a full buffer's
- // worth of data may produce. Yes, this makes the perf optimization
- // less aggressive, in that all reads that asked for fewer than AND
- // returned fewer than _maxCharsPerBuffer chars won't get the user
+ // user's char[]. We absolutely must not write more characters
+ // into the user's buffer than they asked for. Calculating
+ // encoding.GetMaxCharCount(byteLen) each time is potentially very
+ // expensive - instead, cache the number of chars a full buffer's
+ // worth of data may produce. Yes, this makes the perf optimization
+ // less aggressive, in that all reads that asked for fewer than AND
+ // returned fewer than _maxCharsPerBuffer chars won't get the user
// buffer optimization. This affects reads where the end of the
- // Stream comes in the middle somewhere, and when you ask for
+ // Stream comes in the middle somewhere, and when you ask for
// fewer chars than your buffer could produce.
readToUserBuffer = userBuffer.Length >= _maxCharsPerBuffer;
if (len == 0)
{
- // EOF but we might have buffered bytes from previous
+ // EOF but we might have buffered bytes from previous
// attempt to detect preamble that needs to be decoded now
if (_byteLen > 0)
{
}
// _isBlocked == whether we read fewer bytes than we asked for.
- // Note we must check it here because CompressBuffer or
+ // Note we must check it here because CompressBuffer or
// DetectEncoding will change byteLen.
_isBlocked = (_byteLen < _byteBuffer.Length);
public override Task<string?> ReadLineAsync()
{
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Read() which a subclass might have overridden.
+ // since it does not call through to Read() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Read) when we are not sure.
if (GetType() != typeof(StreamReader))
public override Task<string> ReadToEndAsync()
{
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Read() which a subclass might have overridden.
+ // since it does not call through to Read() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Read) when we are not sure.
if (GetType() != typeof(StreamReader))
}
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Read() which a subclass might have overridden.
+ // since it does not call through to Read() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Read) when we are not sure.
if (GetType() != typeof(StreamReader))
int charsRead = 0;
- // As a perf optimization, if we had exactly one buffer's worth of
+ // As a perf optimization, if we had exactly one buffer's worth of
// data read in, let's try writing directly to the user's buffer.
bool readToUserBuffer = false;
if (len == 0)
{
- // EOF but we might have buffered bytes from previous
+ // EOF but we might have buffered bytes from previous
// attempts to detect preamble that needs to be decoded now
if (_byteLen > 0)
{
}
// _isBlocked == whether we read fewer bytes than we asked for.
- // Note we must check it here because CompressBuffer or
+ // Note we must check it here because CompressBuffer or
// DetectEncoding will change _byteLen.
_isBlocked = (_byteLen < tmpByteBuffer.Length);
}
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Read() which a subclass might have overridden.
+ // since it does not call through to Read() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Read) when we are not sure.
if (GetType() != typeof(StreamReader))
if (len == 0)
{
- // EOF but we might have buffered bytes from previous
+ // EOF but we might have buffered bytes from previous
// attempt to detect preamble that needs to be decoded now
if (_byteLen > 0)
{
}
// _isBlocked == whether we read fewer bytes than we asked for.
- // Note we must check it here because CompressBuffer or
+ // Note we must check it here because CompressBuffer or
// DetectEncoding will change _byteLen.
_isBlocked = (_byteLen < tmpByteBuffer.Length);
namespace System.IO
{
// This class implements a TextWriter for writing characters to a Stream.
- // This is designed for character output in a particular Encoding,
- // whereas the Stream class is designed for byte input and output.
+ // This is designed for character output in a particular Encoding,
+ // whereas the Stream class is designed for byte input and output.
public class StreamWriter : TextWriter
{
// For UTF-8, the values of 1K for the default buffer size and 4K for the
// performance for in terms of construction time for the StreamWriter and
// write perf. Note that for UTF-8, we end up allocating a 4K byte buffer,
// which means we take advantage of adaptive buffering code.
- // The performance using UnicodeEncoding is acceptable.
+ // The performance using UnicodeEncoding is acceptable.
private const int DefaultBufferSize = 1024; // char[]
private const int DefaultFileStreamBufferSize = 4096;
private const int MinBufferSize = 128;
private readonly bool _closable;
private bool _disposed;
- // We don't guarantee thread safety on StreamWriter, but we should at
+ // We don't guarantee thread safety on StreamWriter, but we should at
// least prevent users from trying to write anything while an Async
// write from the same thread is in progress.
private Task _asyncWriteTask = Task.CompletedTask;
private void CheckAsyncTaskInProgress()
{
- // We are not locking the access to _asyncWriteTask because this is not meant to guarantee thread safety.
+ // We are not locking the access to _asyncWriteTask because this is not meant to guarantee thread safety.
// We are simply trying to deter calling any Write APIs while an async Write from the same thread is in progress.
if (!_asyncWriteTask.IsCompleted)
{
private static void ThrowAsyncIOInProgress() =>
throw new InvalidOperationException(SR.InvalidOperation_AsyncIOInProgress);
- // The high level goal is to be tolerant of encoding errors when we read and very strict
- // when we write. Hence, default StreamWriter encoding will throw on encoding error.
- // Note: when StreamWriter throws on invalid encoding chars (for ex, high surrogate character
- // D800-DBFF without a following low surrogate character DC00-DFFF), it will cause the
- // internal StreamWriter's state to be irrecoverable as it would have buffered the
- // illegal chars and any subsequent call to Flush() would hit the encoding error again.
- // Even Close() will hit the exception as it would try to flush the unwritten data.
- // Maybe we can add a DiscardBufferedData() method to get out of such situation (like
+ // The high level goal is to be tolerant of encoding errors when we read and very strict
+ // when we write. Hence, default StreamWriter encoding will throw on encoding error.
+ // Note: when StreamWriter throws on invalid encoding chars (for ex, high surrogate character
+ // D800-DBFF without a following low surrogate character DC00-DFFF), it will cause the
+ // internal StreamWriter's state to be irrecoverable as it would have buffered the
+ // illegal chars and any subsequent call to Flush() would hit the encoding error again.
+ // Even Close() will hit the exception as it would try to flush the unwritten data.
+ // Maybe we can add a DiscardBufferedData() method to get out of such situation (like
// StreamReader though for different reason). Either way, the buffered data will be lost!
private static Encoding UTF8NoBOM => EncodingCache.UTF8NoBOM;
{
}
- // Creates a new StreamWriter for the given stream. The
- // character encoding is set by encoding and the buffer size,
- // in number of 16-bit characters, is set by bufferSize.
- //
+ // Creates a new StreamWriter for the given stream. The
+ // character encoding is set by encoding and the buffer size,
+ // in number of 16-bit characters, is set by bufferSize.
+ //
public StreamWriter(Stream stream, Encoding encoding, int bufferSize)
: this(stream, encoding, bufferSize, false)
{
public StreamWriter(string path, bool append, Encoding encoding, int bufferSize) :
this(ValidateArgsAndOpenPath(path, append, encoding, bufferSize), encoding, bufferSize, leaveOpen: false)
- {
+ {
}
private static Stream ValidateArgsAndOpenPath(string path, bool append, Encoding encoding, int bufferSize)
try
{
// We need to flush any buffered data if we are being closed/disposed.
- // Also, we never close the handles for stdout & friends. So we can safely
- // write any buffered data to those streams even during finalization, which
+ // Also, we never close the handles for stdout & friends. So we can safely
+ // write any buffered data to those streams even during finalization, which
// is generally the right thing to do.
if (!_disposed && disposing)
{
private void CloseStreamFromDispose(bool disposing)
{
- // Dispose of our resources if this StreamWriter is closable.
+ // Dispose of our resources if this StreamWriter is closable.
if (_closable && !_disposed)
{
try
{
// Attempt to close the stream even if there was an IO error from Flushing.
// Note that Stream.Close() can potentially throw here (may or may not be
- // due to the same Flush error). In this case, we still need to ensure
- // cleaning up internal resources, hence the finally block.
+ // due to the same Flush error). In this case, we still need to ensure
+ // cleaning up internal resources, hence the finally block.
if (disposing)
{
_stream.Close();
{
// flushEncoder should be true at the end of the file and if
// the user explicitly calls Flush (though not if AutoFlush is true).
- // This is required to flush any dangling characters from our UTF-7
+ // This is required to flush any dangling characters from our UTF-7
// and UTF-8 encoders.
ThrowIfDisposed();
public override Task WriteAsync(char value)
{
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Write() which a subclass might have overridden.
+ // since it does not call through to Write() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Write) when we are not sure.
if (GetType() != typeof(StreamWriter))
public override Task WriteAsync(string? value)
{
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Write() which a subclass might have overridden.
+ // since it does not call through to Write() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Write) when we are not sure.
if (GetType() != typeof(StreamWriter))
}
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Write() which a subclass might have overridden.
+ // since it does not call through to Write() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Write) when we are not sure.
if (GetType() != typeof(StreamWriter))
public override Task WriteLineAsync()
{
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Write() which a subclass might have overridden.
+ // since it does not call through to Write() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Write) when we are not sure.
if (GetType() != typeof(StreamWriter))
public override Task WriteLineAsync(char value)
{
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Write() which a subclass might have overridden.
+ // since it does not call through to Write() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Write) when we are not sure.
if (GetType() != typeof(StreamWriter))
}
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Write() which a subclass might have overridden.
+ // since it does not call through to Write() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Write) when we are not sure.
if (GetType() != typeof(StreamWriter))
}
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Write() which a subclass might have overridden.
+ // since it does not call through to Write() which a subclass might have overridden.
// To be safe we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Write) when we are not sure.
if (GetType() != typeof(StreamWriter))
public override Task FlushAsync()
{
// If we have been inherited into a subclass, the following implementation could be incorrect
- // since it does not call through to Flush() which a subclass might have overridden. To be safe
+ // since it does not call through to Flush() which a subclass might have overridden. To be safe
// we will only use this implementation in cases where we know it is safe to do so,
// and delegate to our base class (which will call into Flush) when we are not sure.
if (GetType() != typeof(StreamWriter))
// flushEncoder should be true at the end of the file and if
// the user explicitly calls Flush (though not if AutoFlush is true).
- // This is required to flush any dangling characters from our UTF-7
- // and UTF-8 encoders.
+ // This is required to flush any dangling characters from our UTF-7
+ // and UTF-8 encoders.
ThrowIfDisposed();
CheckAsyncTaskInProgress();
// there are methods on the Stream class to read bytes.
// A subclass must minimally implement the Peek() and Read() methods.
//
- // This class is intended for character input, not bytes.
- // There are methods on the Stream class for reading bytes.
+ // This class is intended for character input, not bytes.
+ // There are methods on the Stream class for reading bytes.
public abstract partial class TextReader : MarshalByRefObject, IDisposable
{
public static readonly TextReader Null = new NullTextReader();
// the input stream. The current position of the TextReader is not changed by
// this operation. The returned value is -1 if no further characters are
// available.
- //
+ //
// This default method simply returns -1.
//
public virtual int Peek()
// Reads the next character from the input stream. The returned value is
// -1 if no further characters are available.
- //
+ //
// This default method simply returns -1.
//
public virtual int Read()
if (ch == -1) break;
buffer[index + n] = (char)ch;
}
-
+
return n;
}
}
}
- // Reads all characters from the current position to the end of the
+ // Reads all characters from the current position to the end of the
// TextReader, and returns them as one string.
public virtual string ReadToEnd()
{
// Blocking version of read. Returns only when count
// characters have been read or the end of the file was reached.
- //
+ //
public virtual int ReadBlock(char[] buffer, int index, int count)
{
int i, n = 0;
/*============================================================
**
-**
-**
**
-** Purpose: Provides a fast, AV free, cross-language way of
+**
+**
+** Purpose: Provides a fast, AV free, cross-language way of
** accessing unmanaged memory in a random fashion.
**
**
namespace System.IO
{
- /// Perf notes: ReadXXX, WriteXXX (for basic types) acquire and release the
+ /// Perf notes: ReadXXX, WriteXXX (for basic types) acquire and release the
/// SafeBuffer pointer rather than relying on generic Read(T) from SafeBuffer because
/// this gives better throughput; benchmarks showed about 12-15% better.
public class UnmanagedMemoryAccessor : IDisposable
[CLSCompliant(false)]
public ulong ReadUInt64(long position) => unchecked((ulong)ReadInt64(position));
- // Reads a struct of type T from unmanaged memory, into the reference pointed to by ref value.
- // Note: this method is not safe, since it overwrites the contents of a structure, it can be
+ // Reads a struct of type T from unmanaged memory, into the reference pointed to by ref value.
+ // Note: this method is not safe, since it overwrites the contents of a structure, it can be
// used to modify the private members of a struct.
// This method is most performant when used with medium to large sized structs
- // (larger than 8 bytes -- though this is number is JIT and architecture dependent). As
- // such, it is best to use the ReadXXX methods for small standard types such as ints, longs,
+ // (larger than 8 bytes -- though this is number is JIT and architecture dependent). As
+ // such, it is best to use the ReadXXX methods for small standard types such as ints, longs,
// bools, etc.
public void Read<T>(long position, out T structure) where T : struct
{
structure = _buffer.Read<T>((ulong)(_offset + position));
}
- // Reads 'count' structs of type T from unmanaged memory, into 'array' starting at 'offset'.
- // Note: this method is not safe, since it overwrites the contents of structures, it can
+ // Reads 'count' structs of type T from unmanaged memory, into 'array' starting at 'offset'.
+ // Note: this method is not safe, since it overwrites the contents of structures, it can
// be used to modify the private members of a struct.
public int ReadArray<T>(long position, T[] array, int offset, int count) where T : struct
{
public void Write(long position, ulong value) => Write(position, unchecked((long)value));
// Writes the struct pointed to by ref value into unmanaged memory. Note that this method
- // is most performant when used with medium to large sized structs (larger than 8 bytes
- // though this is number is JIT and architecture dependent). As such, it is best to use
+ // is most performant when used with medium to large sized structs (larger than 8 bytes
+ // though this is number is JIT and architecture dependent). As such, it is best to use
// the WriteX methods for small standard types such as ints, longs, bools, etc.
public void Write<T>(long position, ref T structure) where T : struct
{
_buffer.Write<T>((ulong)(_offset + position), structure);
}
- // Writes 'count' structs of type T from 'array' (starting at 'offset') into unmanaged memory.
+ // Writes 'count' structs of type T from 'array' (starting at 'offset') into unmanaged memory.
public void WriteArray<T>(long position, T[] array, int offset, int count) where T : struct
{
if (array == null)
namespace System.IO
{
/*
- * This class is used to access a contiguous block of memory, likely outside
- * the GC heap (or pinned in place in the GC heap, but a MemoryStream may
+ * This class is used to access a contiguous block of memory, likely outside
+ * the GC heap (or pinned in place in the GC heap, but a MemoryStream may
* make more sense in those cases). It's great if you have a pointer and
* a length for a section of memory mapped in by someone else and you don't
- * want to copy this into the GC heap. UnmanagedMemoryStream assumes these
+ * want to copy this into the GC heap. UnmanagedMemoryStream assumes these
* two things:
*
* 1) All the memory in the specified block is readable or writable,
* depending on the values you pass to the constructor.
* 2) The lifetime of the block of memory is at least as long as the lifetime
* of the UnmanagedMemoryStream.
- * 3) You clean up the memory when appropriate. The UnmanagedMemoryStream
+ * 3) You clean up the memory when appropriate. The UnmanagedMemoryStream
* currently will do NOTHING to free this memory.
* 4) All calls to Write and WriteByte may not be threadsafe currently.
*
- * It may become necessary to add in some sort of
- * DeallocationMode enum, specifying whether we unmap a section of memory,
- * call free, run a user-provided delegate to free the memory, etc.
+ * It may become necessary to add in some sort of
+ * DeallocationMode enum, specifying whether we unmap a section of memory,
+ * call free, run a user-provided delegate to free the memory, etc.
* We'll suggest user write a subclass of UnmanagedMemoryStream that uses
* a SafeHandle subclass to hold onto the memory.
- *
+ *
*/
/// <summary>
private long _offset;
private FileAccess _access;
private bool _isOpen;
- private Task<int>? _lastReadTask; // The last successful task returned from ReadAsync
+ private Task<int>? _lastReadTask; // The last successful task returned from ReadAsync
/// <summary>
/// Creates a closed stream.
_isOpen = false;
unsafe { _mem = null; }
- // Stream allocates WaitHandles for async calls. So for correctness
+ // Stream allocates WaitHandles for async calls. So for correctness
// call base.Dispose(disposing) for better perf, avoiding waiting
// for the finalizers to run on those types.
base.Dispose(disposing);
}
/// <summary>
- /// Pointer to memory at the current Position in the stream.
+ /// Pointer to memory at the current Position in the stream.
/// </summary>
[CLSCompliant(false)]
public unsafe byte* PositionPointer
EnsureNotClosed();
EnsureReadable();
- // Use a local variable to avoid a race where another thread
+ // Use a local variable to avoid a race where another thread
// changes our position after we decide we can read some bytes.
long pos = Interlocked.Read(ref _position);
long len = Interlocked.Read(ref _length);
/// </summary>
/// <param name="buffer">Buffer to read the bytes to.</param>
/// <param name="offset">Starting index in the buffer.</param>
- /// <param name="count">Maximum number of bytes to read.</param>
+ /// <param name="count">Maximum number of bytes to read.</param>
/// <param name="cancellationToken">Token that can be used to cancel this operation.</param>
/// <returns>Task that can be used to access the number of bytes actually read.</returns>
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
if (_buffer == null)
{
- // Check to see whether we are now expanding the stream and must
+ // Check to see whether we are now expanding the stream and must
// zero any memory in the middle.
if (pos > len)
{
if (n > _capacity)
throw new NotSupportedException(SR.IO_FixedCapacity);
- // Check to see whether we are now expanding the stream and must
+ // Check to see whether we are now expanding the stream and must
// zero any memory in the middle.
// don't do if created from SafeBuffer
if (_buffer == null)
/*============================================================
**
-**
-**
+**
+**
**
** Purpose: Create a Memorystream over an UnmanagedMemoryStream
**
namespace System.IO
{
// Needed for backwards compatibility with V1.x usages of the
- // ResourceManager, where a MemoryStream is now returned as an
+ // ResourceManager, where a MemoryStream is now returned as an
// UnmanagedMemoryStream from ResourceReader.
internal sealed class UnmanagedMemoryStreamWrapper : MemoryStream
{
}
} // class UnmanagedMemoryStreamWrapper
} // namespace
-
{
/// <summary>
/// Purpose: The exception class for running out of memory
- /// but most likely in a non-fatal way that shouldn't
+ /// but most likely in a non-fatal way that shouldn't
/// be affected by escalation policy. Use this for cases
- /// like MemoryFailPoint or a TryAllocate method, where you
+ /// like MemoryFailPoint or a TryAllocate method, where you
/// expect OOM's with no shared state corruption and you
/// want to recover from these errors.
/// </summary>
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public readonly struct IntPtr : IEquatable<IntPtr>, ISerializable
{
- // WARNING: We allow diagnostic tools to directly inspect this member (_value).
- // See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
- // Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
+ // WARNING: We allow diagnostic tools to directly inspect this member (_value).
+ // See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
+ // Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
// Get in touch with the diagnostics team if you have questions.
private readonly unsafe void* _value; // Do not rename (binary serialization)
// --------------------------------------------------------------------------------------
//
-// A class that provides a simple, lightweight implementation of lazy initialization,
-// obviating the need for a developer to implement a custom, thread-safe lazy initialization
+// A class that provides a simple, lightweight implementation of lazy initialization,
+// obviating the need for a developer to implement a custom, thread-safe lazy initialization
// solution.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
private T _value = default!;
/// <summary>
- /// Initializes a new instance of the <see cref="T:System.Threading.Lazy{T}"/> class that
+ /// Initializes a new instance of the <see cref="T:System.Threading.Lazy{T}"/> class that
/// uses <typeparamref name="T"/>'s default constructor for lazy initialization.
/// </summary>
/// <remarks>
// we have to create a copy of state here, and use the copy exclusively from here on in
// so as to ensure thread safety.
LazyHelper? state = _state;
- if (state != null)
+ if (state != null)
{
switch (state.State)
{
/// otherwise, false.</value>
/// <remarks>
/// The initialization of a <see cref="T:System.Lazy{T}"/> instance may result in either
- /// a value being produced or an exception being thrown. If an exception goes unhandled during initialization,
+ /// a value being produced or an exception being thrown. If an exception goes unhandled during initialization,
/// <see cref="IsValueCreated"/> will return false.
/// </remarks>
public bool IsValueCreated => _state == null;
/// <value>The lazily initialized value of the current <see
/// cref="T:System.Threading.Lazy{T}"/>.</value>
/// <exception cref="T:System.MissingMemberException">
- /// The <see cref="T:System.Threading.Lazy{T}"/> was initialized to use the default constructor
+ /// The <see cref="T:System.Threading.Lazy{T}"/> was initialized to use the default constructor
/// of the type being lazily initialized, and that type does not have a public, parameterless constructor.
/// </exception>
/// <exception cref="T:System.MemberAccessException">
- /// The <see cref="T:System.Threading.Lazy{T}"/> was initialized to use the default constructor
+ /// The <see cref="T:System.Threading.Lazy{T}"/> was initialized to use the default constructor
/// of the type being lazily initialized, and permissions to access the constructor were missing.
/// </exception>
/// <exception cref="T:System.InvalidOperationException">
public T Value => _state == null ? _value : CreateValue();
}
- /// <summary>A debugger view of the Lazy<T> to surface additional debugging properties and
+ /// <summary>A debugger view of the Lazy<T> to surface additional debugging properties and
/// to ensure that the Lazy<T> does not become initialized if it was not already.</summary>
internal sealed class LazyDebugView<T>
{
private static bool GetCachedSwitchValueInternal(string switchName, ref int cachedSwitchValue)
{
bool isSwitchEnabled;
-
+
bool hasSwitch = AppContext.TryGetSwitch(switchName, out isSwitchEnabled);
if (!hasSwitch)
{
{
return true;
}
-
+
return false;
}
}
// If the buffer is 1 or 3 bytes in length, let's read a single byte now
// and merge it into our partial result. This will result in partialResult
// having one of the two values below, where AA BB CC are the buffer bytes.
- //
+ //
// (little-endian / big-endian)
// [ AA ] -> 0x0000_80AA / 0xAA80_0000
// [ AA BB CC ] -> 0x0000_80CC / 0xCC80_0000
// If the buffer is 2 or 3 bytes in length, let's read a single ushort now
// and merge it into the partial result. This will result in partialResult
// having one of the two values below, where AA BB CC are the buffer bytes.
- //
+ //
// (little-endian / big-endian)
// [ AA BB ] -> 0x0080_BBAA / 0xAABB_8000
// [ AA BB CC ] -> 0x80CC_BBAA / 0xAABB_CC80 (carried over from above)
**
** Purpose: Some floating-point math operations
**
-**
+**
===========================================================*/
//This class contains only static members and doesn't require serialization.
{
return max;
}
-
+
return value;
}
{
return (val1 >= val2) ? val1 : val2;
}
-
+
public static float Max(float val1, float val2)
{
// This matches the IEEE 754:2019 `maximum` function
}
// Directed rounding: Round up to the next value, toward positive infinity
case MidpointRounding.ToPositiveInfinity:
- {
+ {
value = Ceiling(value);
break;
}
throw new ArgumentException(SR.Format(SR.Argument_InvalidEnumValue, mode, nameof(MidpointRounding)), nameof(mode));
}
}
-
+
value /= power10;
}
}
// Directed rounding: Round up to the next value, toward positive infinity
case MidpointRounding.ToPositiveInfinity:
- {
+ {
x = Ceiling(x);
break;
}
throw new ArgumentException(SR.Format(SR.Argument_InvalidEnumValue, mode, nameof(MidpointRounding)), nameof(mode));
}
}
-
+
x /= power10;
}
public class MemberAccessException : SystemException
{
// Creates a new MemberAccessException with its message string set to
- // the empty string, its HRESULT set to COR_E_MEMBERACCESS,
- // and its ExceptionInfo reference set to null.
+ // the empty string, its HRESULT set to COR_E_MEMBERACCESS,
+ // and its ExceptionInfo reference set to null.
public MemberAccessException()
: base(SR.Arg_AccessException)
{
}
// Creates a new MemberAccessException with its message string set to
- // message, its HRESULT set to COR_E_ACCESS,
- // and its ExceptionInfo reference set to null.
- //
+ // message, its HRESULT set to COR_E_ACCESS,
+ // and its ExceptionInfo reference set to null.
+ //
public MemberAccessException(string? message)
: base(message)
{
{
get
{
- return ClassName == null ? base.Message :
- SR.Format(SR.MissingMethod_Name, ClassName + "." + MemberName +
+ return ClassName == null ? base.Message :
+ SR.Format(SR.MissingMethod_Name, ClassName + "." + MemberName +
(Signature != null ? " " + FormatSignature(Signature) : string.Empty));
}
}
**
**
**
-** Purpose: Exception thrown when a requested method or operation is not
+** Purpose: Exception thrown when a requested method or operation is not
** implemented.
**
**
if (nullableType.IsGenericType && !nullableType.IsGenericTypeDefinition)
{
- // instantiated generic type only
+ // instantiated generic type only
Type genericType = nullableType.GetGenericTypeDefinition();
if (object.ReferenceEquals(genericType, typeof(Nullable<>)))
{
0xC1D238D9,
0x633415D4,
0x0000001C,
-
+
// 10^1024
107, // _length
0x00000000, // _blocks
// s_Pow10UInt32Table stores the results of 10^0 to 10^7.
// s_Pow10BigNumTable stores the results of 10^8, 10^16, 10^32, 10^64, 10^128, 10^256, and 10^512
//
- // For example, let's say exp = 0b111111. We can split the exp to two parts, one is small exp,
- // which 10^smallExp can be represented as uint, another part is 10^bigExp, which must be represented as BigNum.
+ // For example, let's say exp = 0b111111. We can split the exp to two parts, one is small exp,
+ // which 10^smallExp can be represented as uint, another part is 10^bigExp, which must be represented as BigNum.
// So the result should be 10^smallExp * 10^bigExp.
//
- // Calculating 10^smallExp is simple, we just lookup the 10^smallExp from s_Pow10UInt32Table.
- // But here's a bad news: although uint can represent 10^9, exp 9's binary representation is 1001.
- // That means 10^(1011), 10^(1101), 10^(1111) all cannot be stored as uint, we cannot easily say something like:
- // "Any bits <= 3 is small exp, any bits > 3 is big exp". So instead of involving 10^8, 10^9 to s_Pow10UInt32Table,
- // consider 10^8 and 10^9 as a bigNum, so they fall into s_Pow10BigNumTable. Now we can have a simple rule:
+ // Calculating 10^smallExp is simple, we just lookup the 10^smallExp from s_Pow10UInt32Table.
+ // But here's a bad news: although uint can represent 10^9, exp 9's binary representation is 1001.
+ // That means 10^(1011), 10^(1101), 10^(1111) all cannot be stored as uint, we cannot easily say something like:
+ // "Any bits <= 3 is small exp, any bits > 3 is big exp". So instead of involving 10^8, 10^9 to s_Pow10UInt32Table,
+ // consider 10^8 and 10^9 as a bigNum, so they fall into s_Pow10BigNumTable. Now we can have a simple rule:
// "Any bits <= 3 is small exp, any bits > 3 is big exp".
//
- // For 0b111111, we first calculate 10^(smallExp), which is 10^(7), now we can shift right 3 bits, prepare to calculate the bigExp part,
+ // For 0b111111, we first calculate 10^(smallExp), which is 10^(7), now we can shift right 3 bits, prepare to calculate the bigExp part,
// the exp now becomes 0b000111.
//
// Apparently the lowest bit of bigExp should represent 10^8 because we have already shifted 3 bits for smallExp, so s_Pow10BigNumTable[0] = 10^8.
{
// This is a port of the `Grisu3` implementation here: https://github.com/google/double-conversion/blob/a711666ddd063eb1e4b181a6cb981d39a1fc8bac/double-conversion/fast-dtoa.cc
// The backing algorithm and the proofs behind it are described in more detail here: http://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf
- // ========================================================================================================================================
+ // ========================================================================================================================================
//
// Overview:
//
// number < (1 << (numberBits + 1))
private static uint BiggestPowerTen(uint number, int numberBits, out int exponentPlusOne)
{
- // Inspired by the method for finding an integer log base 10 from here:
+ // Inspired by the method for finding an integer log base 10 from here:
// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
Debug.Assert(number < (1U << (numberBits + 1)));
{
// We need 1 additional byte, per length, for the terminating null
internal const int DecimalNumberBufferLength = 29 + 1 + 1; // 29 for the longest input + 1 for rounding
- internal const int DoubleNumberBufferLength = 767 + 1 + 1; // 767 for the longest input + 1 for rounding: 4.9406564584124654E-324
+ internal const int DoubleNumberBufferLength = 767 + 1 + 1; // 767 for the longest input + 1 for rounding: 4.9406564584124654E-324
internal const int Int32NumberBufferLength = 10 + 1; // 10 for the longest input: 2,147,483,647
internal const int Int64NumberBufferLength = 19 + 1; // 19 for the longest input: 9,223,372,036,854,775,807
internal const int SingleNumberBufferLength = 112 + 1 + 1; // 112 for the longest input + 1 for rounding: 1.40129846E-45
-// Licensed to the .NET Foundation under one or more agreements.
+// 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.
}
this = Unsafe.ReadUnaligned<Vector<T>>(ref MemoryMarshal.GetReference(values));
}
-
+
/// <summary>
/// Constructs a vector from the given <see cref="ReadOnlySpan{T}"/>. The span must contain at least <see cref="Vector{T}.Count"/> elements.
/// </summary>
}
/// <summary>
- /// Returns an integral vector whose elements signal whether the elements in left were greater than or equal to
+ /// Returns an integral vector whose elements signal whether the elements in left were greater than or equal to
/// their corresponding elements in right.
/// </summary>
/// <param name="left">The first vector to compare.</param>
}
/// <summary>
- /// Returns a boolean indicating whether all of the elements in left are greater than or equal to
+ /// Returns a boolean indicating whether all of the elements in left are greater than or equal to
/// their corresponding elements in right.
/// </summary>
/// <param name="left">The first vector to compare.</param>
}
/// <summary>
- /// Returns a new vector whose values are the result of dividing the first vector's elements
+ /// Returns a new vector whose values are the result of dividing the first vector's elements
/// by the corresponding elements in the second vector.
/// </summary>
/// <param name="left">The first source vector.</param>
namespace System
{
- // The Object is the root class for all object in the CLR System. Object
+ // The Object is the root class for all object in the CLR System. Object
// is the super class for all other CLR objects and provide a set of methods and low level
// services to subclasses. These services include object synchronization and support for clone
// operations.
return GetType().ToString();
}
- // Returns a boolean indicating if the passed in object obj is
+ // Returns a boolean indicating if the passed in object obj is
// Equal to this. Equality is defined as object equality for reference
// types and bitwise equality for value types using a loader trick to
// replace Equals with EqualsValue for value types).
**
** Purpose: Attribute for functions, etc that will be removed.
**
-**
+**
===========================================================*/
namespace System
// This attribute is attached to members that are not to be used any longer.
// Message is some human readable explanation of what to use
// Error indicates if the compiler should treat usage of such a method as an
- // error. (this would be used if the actual implementation of the obsolete
+ // error. (this would be used if the actual implementation of the obsolete
// method's implementation had changed).
- //
+ //
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum |
AttributeTargets.Interface | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Delegate
, Inherited = false)]
/// <typeparam name="T">Specifies the type of the progress report value.</typeparam>
/// <remarks>
/// Any handler provided to the constructor or event handlers registered with
- /// the <see cref="ProgressChanged"/> event are invoked through a
+ /// the <see cref="ProgressChanged"/> event are invoked through a
/// <see cref="System.Threading.SynchronizationContext"/> instance captured
/// when the instance is constructed. If there is no current SynchronizationContext
/// at the time of construction, the callbacks will be invoked on the ThreadPool.
/// <param name="handler">
/// A handler to invoke for each reported progress value. This handler will be invoked
/// in addition to any delegates registered with the <see cref="ProgressChanged"/> event.
- /// Depending on the <see cref="System.Threading.SynchronizationContext"/> instance captured by
+ /// Depending on the <see cref="System.Threading.SynchronizationContext"/> instance captured by
/// the <see cref="Progress{T}"/> at construction, it's possible that this handler instance
/// could be invoked concurrently with itself.
/// </param>
/// <summary>Raised for each reported progress value.</summary>
/// <remarks>
- /// Handlers registered with this event will be invoked on the
+ /// Handlers registered with this event will be invoked on the
/// <see cref="System.Threading.SynchronizationContext"/> captured when the instance was constructed.
/// </remarks>
public event EventHandler<T>? ProgressChanged;
protected virtual void OnReport(T value)
{
// If there's no handler, don't bother going through the sync context.
- // Inside the callback, we'll need to check again, in case
+ // Inside the callback, we'll need to check again, in case
// an event handler is removed between now and then.
Action<T>? handler = _handler;
EventHandler<T>? changedEvent = ProgressChanged;
public class Random
{
//
- // Private Constants
+ // Private Constants
//
private const int MBIG = int.MaxValue;
private const int MSEED = 161803398;
//
// Public Instance Methods
- //
+ //
/*=====================================Next=====================================
private double GetSampleForLargeRange()
{
- // The distribution of double value returned by Sample
+ // The distribution of double value returned by Sample
// is not distributed well enough for a large range.
// If we use Sample for a range [int.MinValue..int.MaxValue)
// We will end up getting even numbers only.
{
if (assemblyFile == null)
throw new ArgumentNullException(nameof(assemblyFile));
-
+
string fullPath = Path.GetFullPath(assemblyFile);
if (!s_loadFromHandlerSet)
public uint AlgorithmId { get; }
}
}
-
public string Company { get; }
}
}
-
public string Configuration { get; }
}
}
-
WindowsRuntime = 1,
}
}
-
public string Copyright { get; }
}
}
-
public string Culture { get; }
}
}
-
public string DefaultAlias { get; }
}
}
-
public bool DelaySign { get; }
}
}
-
public string Description { get; }
}
}
-
public string Version { get; }
}
}
-
public string InformationalVersion { get; }
}
}
-
public string KeyFile { get; }
}
}
-
public string KeyName { get; }
}
}
-
public string? Value { get; }
}
}
-
{
public sealed partial class AssemblyName : ICloneable, IDeserializationCallback, ISerializable
{
- // If you modify any of these fields, you must also update the
+ // If you modify any of these fields, you must also update the
// AssemblyBaseObject structure in object.h
private string? _name;
private byte[]? _publicKey;
}
// Set and get the name of the assembly. If this is a weak Name
- // then it optionally contains a site. For strong assembly names,
+ // then it optionally contains a site. For strong assembly names,
// the name partitions up the strong name's namespace
public string? Name
{
private static readonly char[] s_hexUpperChars = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
- internal const char c_DummyChar = (char)0xFFFF; //An Invalid Unicode character used as a dummy char passed into the parameter
+ internal const char c_DummyChar = (char)0xFFFF; //An Invalid Unicode character used as a dummy char passed into the parameter
private const short c_MaxAsciiCharsReallocate = 40;
private const short c_MaxUnicodeCharsReallocate = 40;
private const short c_MaxUTF_8BytesPerUnicodeChar = 4;
public string Product { get; }
}
}
-
public string Countersignature { get; }
}
}
-
public string Title { get; }
}
}
-
public string Trademark { get; }
}
}
-
public string Version { get; }
}
}
-
ExactBinding = 0x010000, // Bind with Exact Type matching, No Change type
SuppressChangeType = 0x020000,
- // DefaultValueBinding will return the set of methods having ArgCount or
+ // DefaultValueBinding will return the set of methods having ArgCount or
// more parameters. This is used for default values, etc.
OptionalParamBinding = 0x040000,
}
public int Token { get; }
-
+
public override int GetHashCode() => Token;
-
+
public override bool Equals(object? obj) => obj is FieldToken ft && Equals(ft);
public bool Equals(FieldToken obj) => obj.Token == Token && obj._class == _class;
/*============================================================
**
-**
-**
**
-**
+**
+**
+**
**
** Purpose: Represents a Label to the ILGenerator class.
**
-**
+**
===========================================================*/
namespace System.Reflection.Emit
{
- // The Label class is an opaque representation of a label used by the
+ // The Label class is an opaque representation of a label used by the
// ILGenerator class. The token is used to mark where labels occur in the IL
- // stream and then the necessary offsets are put back in the code when the ILGenerator
+ // stream and then the necessary offsets are put back in the code when the ILGenerator
// is passed to the MethodWriter.
// Labels are created by using ILGenerator.CreateLabel and their position is set
// by using ILGenerator.MarkLabel.
// See the LICENSE file in the project root for more information.
namespace System.Reflection.Emit
-{
+{
/// <summary>
/// The ParameterToken class is an opaque representation of the Token returned
/// by the Metadata to represent the parameter.
Token = str;
}
- // Returns the metadata token for this particular string.
+ // Returns the metadata token for this particular string.
// Generated by a call to Module.GetStringConstant().
//
public int Token { get; }
public static bool operator !=(TypeToken a, TypeToken b) => !(a == b);
}
}
-
// member access mask - Use this mask to retrieve accessibility information.
FieldAccessMask = 0x0007,
PrivateScope = 0x0000, // Member not referenceable.
- Private = 0x0001, // Accessible only by the parent type.
+ Private = 0x0001, // Accessible only by the parent type.
FamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly.
Assembly = 0x0003, // Accessibly by anyone in the Assembly.
- Family = 0x0004, // Accessible only by type and sub-types.
+ Family = 0x0004, // Accessible only by type and sub-types.
FamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly.
- Public = 0x0006, // Accessibly by anyone who has visibility to this scope.
+ Public = 0x0006, // Accessibly by anyone who has visibility to this scope.
// end member access mask
// field contract attributes.
DefaultConstructorConstraint = 0x0010,
}
}
-
{
// Return the requested method if it is implemented by the Reflection object. The
// match is based upon the name and DescriptorInfo which describes the signature
- // of the method.
+ // of the method.
MethodInfo? GetMethod(string name, BindingFlags bindingAttr, Binder? binder, Type[] types, ParameterModifier[]? modifiers);
// Return the requested method if it is implemented by the Reflection object. The
// indexing. Return null if no property is found.
PropertyInfo? GetProperty(string name, BindingFlags bindingAttr, Binder? binder, Type? returnType, Type[] types, ParameterModifier[]? modifiers);
- // Returns an array of PropertyInfos for all the properties defined on
+ // Returns an array of PropertyInfos for all the properties defined on
// the Reflection object.
PropertyInfo[] GetProperties(BindingFlags bindingAttr);
// Description of the Binding Process.
// We must invoke a method that is accessible and for which the provided
// parameters have the most specific match. A method may be called if
- // 1. The number of parameters in the method declaration equals the number of
+ // 1. The number of parameters in the method declaration equals the number of
// arguments provided to the invocation
// 2. The type of each argument can be converted by the binder to the
// type of the type of the parameter.
- //
+ //
// The binder will find all of the matching methods. These method are found based
// upon the type of binding requested (MethodInvoke, Get/Set Properties). The set
// of methods is filtered by the name, number of arguments and a set of search modifiers
// defined in the Binder.
- //
+ //
// After the method is selected, it will be invoked. Accessibility is checked
// at that point. The search may be control which set of methods are searched based
// upon the accessibility attribute associated with the method.
- //
+ //
// The BindToMethod method is responsible for selecting the method to be invoked.
// For the default binder, the most specific method will be selected.
- //
+ //
// This will invoke a specific member...
object? InvokeMember(string name, BindingFlags invokeAttr, Binder? binder, object? target, object?[]? args, ParameterModifier[]? modifiers, CultureInfo? culture, string[]? namedParameters);
TypeInfo GetTypeInfo();
}
}
-
public virtual ResourceLocation ResourceLocation { get; }
}
}
-
{
get
{
- // This check is necessary because for some reason, Type adds a new "Module" property that hides the inherited one instead
+ // This check is necessary because for some reason, Type adds a new "Module" property that hides the inherited one instead
// of overriding.
if (this is Type type)
// member access mask - Use this mask to retrieve accessibility information.
MemberAccessMask = 0x0007,
PrivateScope = 0x0000, // Member not referenceable.
- Private = 0x0001, // Accessible only by the parent type.
+ Private = 0x0001, // Accessible only by the parent type.
FamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly.
Assembly = 0x0003, // Accessibly by anyone in the Assembly.
- Family = 0x0004, // Accessible only by type and sub-types.
+ Family = 0x0004, // Accessible only by type and sub-types.
FamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly.
- Public = 0x0006, // Accessibly by anyone who has visibility to this scope.
+ Public = 0x0006, // Accessibly by anyone who has visibility to this scope.
// end member access mask
// method contract attributes.
public virtual IList<ExceptionHandlingClause> ExceptionHandlingClauses => throw new ArgumentNullException("array");
}
}
-
public enum MethodImplAttributes
{
// code impl mask
- CodeTypeMask = 0x0003, // Flags about code type.
+ CodeTypeMask = 0x0003, // Flags about code type.
IL = 0x0000, // Method impl is IL.
- Native = 0x0001, // Method impl is native.
- OPTIL = 0x0002, // Method impl is OPTIL
+ Native = 0x0001, // Method impl is native.
+ OPTIL = 0x0002, // Method impl is OPTIL
Runtime = 0x0003, // Method impl is provided by the runtime.
// end code impl mask
{
public abstract partial class MethodInfo : MethodBase
{
-#if CORERT
+#if CORERT
public // Needs to be public so that Reflection.Core can see it.
#else
internal
public override bool Equals(object? o) => base.Equals(o);
public override int GetHashCode() => base.GetHashCode();
-
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Module? left, Module? right)
{
private const BindingFlags DefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
- // FilterTypeName
+ // FilterTypeName
// This method will filter the class based upon the name. It supports
// a trailing wild card.
private static bool FilterTypeNameImpl(Type cls, object filterCriteria, StringComparison comparison)
{
public delegate Module ModuleResolveEventHandler(object sender, ResolveEventArgs e);
}
-
public bool StripAfterObfuscation { get; set; } = true;
}
}
-
public string? Feature { get; set; } = "all";
}
}
-
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-// ParameterAttributes is an enum defining the attributes that may be
+// ParameterAttributes is an enum defining the attributes that may be
// associated with a Parameter. These are defined in CorHdr.h.
namespace System.Reflection
public enum ParameterAttributes
{
None = 0x0000, // no flag is specified
- In = 0x0001, // Param is [In]
- Out = 0x0002, // Param is [Out]
- Lcid = 0x0004, // Param is [lcid]
+ In = 0x0001, // Param is [In]
+ Out = 0x0002, // Param is [Out]
+ Lcid = 0x0004, // Param is [lcid]
Retval = 0x0008, // Param is [Retval]
- Optional = 0x0010, // Param is optional
+ Optional = 0x0010, // Param is optional
HasDefault = 0x1000, // Param has default value.
HasFieldMarshal = 0x2000, // Param has FieldMarshal.
Preferred32Bit = 0x10,
}
}
-
SpecialName = 0x0200, // property is special. Name describes how.
RTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding.
- HasDefault = 0x1000, // Property has default
+ HasDefault = 0x1000, // Property has default
Reserved2 = 0x2000,
Reserved3 = 0x4000,
{
Debug.Assert(rank > 0);
Debug.Assert(rank == 1 || isMultiDim);
-
+
_rank = rank;
_isMultiDim = isMultiDim;
}
-
+
protected sealed override bool IsArrayImpl() => true;
protected sealed override bool IsByRefImpl() => false;
protected sealed override bool IsPointerImpl() => false;
-
+
public sealed override bool IsSZArray => !_isMultiDim;
public sealed override bool IsVariableBoundArray => _isMultiDim;
-
+
public sealed override int GetArrayRank() => _rank;
-
+
protected sealed override string Suffix
{
get
return "[" + new string(',', _rank - 1) + "]";
}
}
-
+
private readonly int _rank;
private readonly bool _isMultiDim;
}
: base(elementType)
{
}
-
+
protected sealed override bool IsArrayImpl() => false;
protected sealed override bool IsByRefImpl() => true;
protected sealed override bool IsPointerImpl() => false;
-
+
public sealed override bool IsSZArray => false;
public sealed override bool IsVariableBoundArray => false;
-
+
public sealed override int GetArrayRank() => throw new ArgumentException(SR.Argument_HasToBeArrayClass);
-
+
protected sealed override string Suffix => "&";
}
}
_genericTypeDefinition = genericTypeDefinition;
_genericTypeArguments = typeArguments;
}
-
+
public sealed override bool IsTypeDefinition => false;
public sealed override bool IsGenericTypeDefinition => false;
protected sealed override bool HasElementTypeImpl() => false;
return false;
}
}
-
+
internal sealed override SignatureType? ElementType => null;
public sealed override int GetArrayRank() => throw new ArgumentException(SR.Argument_HasToBeArrayClass);
public sealed override Type GetGenericTypeDefinition() => _genericTypeDefinition;
public sealed override int GenericParameterPosition => throw new InvalidOperationException(SR.Arg_NotGenericParameter);
public sealed override string Name => _genericTypeDefinition.Name;
public sealed override string? Namespace => _genericTypeDefinition.Namespace;
-
+
public sealed override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append(']');
return sb.ToString();
}
-
+
private readonly Type _genericTypeDefinition;
private readonly Type[] _genericTypeArguments;
}
Debug.Assert(position >= 0);
_position = position;
}
-
+
public sealed override bool IsTypeDefinition => false;
public sealed override bool IsGenericTypeDefinition => false;
protected sealed override bool HasElementTypeImpl() => false;
public sealed override bool IsGenericParameter => true;
public abstract override bool IsGenericMethodParameter { get; }
public sealed override bool ContainsGenericParameters => true;
-
+
internal sealed override SignatureType? ElementType => null;
public sealed override int GetArrayRank() => throw new ArgumentException(SR.Argument_HasToBeArrayClass);
public sealed override Type GetGenericTypeDefinition() => throw new InvalidOperationException(SR.InvalidOperation_NotGenericType);
public sealed override int GenericParameterPosition => _position;
public abstract override string Name { get; }
public sealed override string? Namespace => null;
-
+
public sealed override string ToString() => Name;
-
+
private readonly int _position;
}
}
{
protected SignatureHasElementType(SignatureType elementType)
{
- Debug.Assert(elementType != null);
+ Debug.Assert(elementType != null);
_elementType = elementType;
}
-
+
public sealed override bool IsTypeDefinition => false;
public sealed override bool IsGenericTypeDefinition => false;
protected sealed override bool HasElementTypeImpl() => true;
public sealed override bool IsGenericTypeParameter => false;
public sealed override bool IsGenericMethodParameter => false;
public sealed override bool ContainsGenericParameters => _elementType.ContainsGenericParameters;
-
+
internal sealed override SignatureType? ElementType => _elementType;
public abstract override int GetArrayRank();
public sealed override Type GetGenericTypeDefinition() => throw new InvalidOperationException(SR.InvalidOperation_NotGenericType);
public sealed override int GenericParameterPosition => throw new InvalidOperationException(SR.Arg_NotGenericParameter);
public sealed override string Name => _elementType.Name + Suffix;
public sealed override string? Namespace => _elementType.Namespace;
-
+
public sealed override string ToString() => _elementType.ToString() + Suffix;
-
- protected abstract string Suffix { get; }
-
+
+ protected abstract string Suffix { get; }
+
private readonly SignatureType _elementType;
}
}
: base(elementType)
{
}
-
+
protected sealed override bool IsArrayImpl() => false;
protected sealed override bool IsByRefImpl() => false;
protected sealed override bool IsPointerImpl() => true;
-
+
public sealed override bool IsSZArray => false;
public sealed override bool IsVariableBoundArray => false;
-
+
public sealed override int GetArrayRank() => throw new ArgumentException(SR.Argument_HasToBeArrayClass);
-
+
protected sealed override string Suffix => "*";
}
}
public sealed override int GetHashCode() => base.GetHashCode();
#endif
public sealed override Type UnderlyingSystemType => this; // Equals(Type) depends on this.
-
+
// Naming and diagnostics
public abstract override string Name { get; }
public abstract override string? Namespace { get; }
static class SignatureTypeExtensions
{
/// <summary>
- /// This is semantically identical to
- ///
+ /// This is semantically identical to
+ ///
/// parameter.ParameterType == pattern.TryResolveAgainstGenericMethod(parameter.Member)
- ///
+ ///
/// but without the allocation overhead of TryResolve.
/// </summary>
public static bool MatchesParameterTypeExactly(this Type pattern, ParameterInfo parameter)
}
/// <summary>
- /// This is semantically identical to
- ///
+ /// This is semantically identical to
+ ///
/// actual == pattern.TryResolveAgainstGenericMethod(parameterMember)
- ///
+ ///
/// but without the allocation overhead of TryResolve.
/// </summary>
internal static bool MatchesExactly(this SignatureType pattern, Type actual)
/// with its corresponding generic parameter definition. This is slow so MatchesExactly or MatchesParameterTypeExactly should be
/// substituted instead whenever possible. This is only used by the DefaultBinder when its fast-path checks have been exhausted and
/// it needs to call non-trivial methods like IsAssignableFrom which SignatureTypes will never support.
- ///
+ ///
/// Because this method is used to eliminate method candidates in a GetMethod() lookup, it is entirely possible that the Type
/// might not be creatable due to conflicting generic constraints. Since this merely implies that this candidate is not
/// the method we're looking for, we return null rather than let the TypeLoadException bubble up. The DefaultBinder will catch
{
return signatureType.TryResolve(genericMethod.GetGenericArguments());
}
-
+
private static Type? TryResolve(this SignatureType signatureType, Type[] genericMethodParameters)
{
if (signatureType.IsSZArray)
return null;
}
}
-
+
private static Type? TryMakeArrayType(this Type type)
{
try
return null;
}
}
-
+
private static Type? TryMakeArrayType(this Type type, int rank)
{
try
return null;
}
}
-
+
private static Type? TryMakeByRefType(this Type type)
{
try
return null;
}
}
-
+
private static Type? TryMakePointerType(this Type type)
{
try
return null;
}
}
-
+
private static Type? TryMakeGenericType(this Type type, Type[] instantiation)
{
try
// See the LICENSE file in the project root for more information.
// TypeDelegator
-//
+//
// This class wraps a Type object and delegates all methods to that Type.
using CultureInfo = System.Globalization.CultureInfo;
/*============================================================
**
-**
-**
**
**
-** Purpose: A collection of quick methods for comparing
+**
+**
+** Purpose: A collection of quick methods for comparing
** resource keys (strings)
**
-**
+**
===========================================================*/
#nullable enable
}
// This hash function MUST be publically documented with the resource
- // file format, AND we may NEVER change this hash function's return
+ // file format, AND we may NEVER change this hash function's return
// value (without changing the file format).
internal static int HashFunction(string key)
{
- // Never change this hash function. We must standardize it so that
+ // Never change this hash function. We must standardize it so that
// others can read & write our .resources files. Additionally, we
// have a copy of it in InternalResGen as well.
uint hash = 5381;
return string.Equals(sa, sb);
}
- // Input is one string to compare with, and a byte[] containing chars in
+ // Input is one string to compare with, and a byte[] containing chars in
// little endian unicode. Pass in the number of valid chars.
public static unsafe int CompareOrdinal(string a, byte[] bytes, int bCharLength)
{
}
}
}
-
** Purpose: Searches for resources on disk, used for file-
** based resource lookup.
**
-**
+**
===========================================================*/
using System.Collections.Generic;
_mediator = mediator;
}
- // Consider modifying IResourceGroveler interface (hence this method signature) when we figure out
- // serialization compat story for moving ResourceManager members to either file-based or
+ // Consider modifying IResourceGroveler interface (hence this method signature) when we figure out
+ // serialization compat story for moving ResourceManager members to either file-based or
// manifest-based classes. Want to continue tightening the design to get rid of unused params.
public ResourceSet? GrovelForResourceSet(CultureInfo culture, Dictionary<string, ResourceSet> localResourceSets, bool tryParents, bool createIfNotExists)
{
return rs;
}
- // Given a CultureInfo, it generates the path &; file name for
+ // Given a CultureInfo, it generates the path &; file name for
// the .resources file for that CultureInfo. This method will grovel
// the disk looking for the correct file name & path. Uses CultureInfo's
- // Name property. If the module directory was set in the ResourceManager
+ // Name property. If the module directory was set in the ResourceManager
// constructor, we'll look there first. If it couldn't be found in the module
// diretory or the module dir wasn't provided, look in the current
// directory.
Debug.Assert(culture != null, "culture shouldn't be null; check caller");
Debug.Assert(fileName != null, "fileName shouldn't be null; check caller");
- // If we have a moduleDir, check there first. Get module fully
+ // If we have a moduleDir, check there first. Get module fully
// qualified name, append path to that.
if (_mediator.ModuleDir != null)
{
/*============================================================
**
-**
-**
+**
+**
**
**
** Purpose: Interface for resource grovelers
**
-**
+**
===========================================================*/
using System;
/*============================================================
**
-**
-**
+**
+**
**
**
** Purpose: Abstraction to read streams of resources.
**
-**
+**
===========================================================*/
using System;
/*============================================================
**
-**
-**
+**
+**
**
**
** Purpose: Exception for a missing satellite assembly needed
/*============================================================
**
-**
-**
**
**
-** Purpose: Encapsulates CultureInfo fallback for resource
+**
+**
+** Purpose: Encapsulates CultureInfo fallback for resource
** lookup
**
-**
+**
===========================================================*/
using System;
//
// 1) For Framework assemblies, we always use satellite assembly based lookup.
// 2) For non-FX assemblies:
- //
+ //
// a) If the assembly lives under PLATFORM_RESOURCE_ROOTS (as specified by the host during AppDomain creation),
// then we will use satellite assembly based lookup in assemblies like *.resources.dll.
- //
+ //
// b) For any other non-FX assembly, we will use the modern resource manager with the premise that app package
// contains the PRI resources.
//
namespace System.Resources
{
// Resource Manager exposes an assembly's resources to an application for
- // the correct CultureInfo. An example would be localizing text for a
- // user-visible message. Create a set of resource files listing a name
+ // the correct CultureInfo. An example would be localizing text for a
+ // user-visible message. Create a set of resource files listing a name
// for a message and its value, compile them using ResGen, put them in
- // an appropriate place (your assembly manifest(?)), then create a Resource
+ // an appropriate place (your assembly manifest(?)), then create a Resource
// Manager and query for the name of the message you want. The Resource
// Manager will use CultureInfo.GetCurrentUICulture() to look
// up a resource for your user's locale settings.
- //
+ //
// Users should ideally create a resource file for every culture, or
- // at least a meaningful subset. The filenames will follow the naming
+ // at least a meaningful subset. The filenames will follow the naming
// scheme:
- //
+ //
// basename.culture name.resources
- //
- // The base name can be the name of your application, or depending on
- // the granularity desired, possibly the name of each class. The culture
- // name is determined from CultureInfo's Name property.
+ //
+ // The base name can be the name of your application, or depending on
+ // the granularity desired, possibly the name of each class. The culture
+ // name is determined from CultureInfo's Name property.
// An example file name may be MyApp.en-US.resources for
// MyApp's US English resources.
- //
+ //
// -----------------
// Refactoring Notes
// -----------------
// In Feb 08, began first step of refactoring ResourceManager to improve
// maintainability (sd changelist 3012100). This resulted in breaking
// apart the InternalGetResourceSet "big loop" so that the file-based
- // and manifest-based lookup was located in separate methods.
+ // and manifest-based lookup was located in separate methods.
// In Apr 08, continued refactoring so that file-based and manifest-based
// concerns are encapsulated by separate classes. At construction, the
- // ResourceManager creates one of these classes based on whether the
- // RM will need to use file-based or manifest-based resources, and
+ // ResourceManager creates one of these classes based on whether the
+ // RM will need to use file-based or manifest-based resources, and
// afterwards refers to this through the interface IResourceGroveler.
- //
+ //
// Serialization Compat: Ideally, we could have refactored further but
// this would have broken serialization compat. For example, the
- // ResourceManager member UseManifest and UseSatelliteAssem are no
+ // ResourceManager member UseManifest and UseSatelliteAssem are no
// longer relevant on ResourceManager. Similarly, other members could
- // ideally be moved to the file-based or manifest-based classes
+ // ideally be moved to the file-based or manifest-based classes
// because they are only relevant for those types of lookup.
//
- // Solution now / in the future:
+ // Solution now / in the future:
// For now, we simply use a mediator class so that we can keep these
// members on ResourceManager but allow the file-based and manifest-
// based classes to access/set these members in a uniform way. See
// ResourceManagerMediator.
- // We encapsulate fallback logic in a fallback iterator class, so that
+ // We encapsulate fallback logic in a fallback iterator class, so that
// this logic isn't duplicated in several methods.
- //
+ //
// In the future, we can also look into further factoring and better
// design of IResourceGroveler interface to accommodate unused parameters
// that don't make sense for either file-based or manifest-based lookup paths.
//
// Benefits of this refactoring:
- // - Makes it possible to understand what the ResourceManager does,
- // which is key for maintainability.
+ // - Makes it possible to understand what the ResourceManager does,
+ // which is key for maintainability.
// - Makes the ResourceManager more extensible by identifying and
// encapsulating what varies
- // - Unearthed a bug that's been lurking a while in file-based
+ // - Unearthed a bug that's been lurking a while in file-based
// lookup paths for InternalGetResourceSet if createIfNotExists is
// false.
- // - Reuses logic, e.g. by breaking apart the culture fallback into
- // the fallback iterator class, we don't have to repeat the
+ // - Reuses logic, e.g. by breaking apart the culture fallback into
+ // the fallback iterator class, we don't have to repeat the
// sometimes confusing fallback logic across multiple methods
- // - Fxcop violations reduced to 1/5th of original count. Most
+ // - Fxcop violations reduced to 1/5th of original count. Most
// importantly, code complexity violations disappeared.
// - Finally, it got rid of dead code paths. Because the big loop was
- // so confusing, it masked unused chunks of code. Also, dividing
- // between file-based and manifest-based allowed functionaliy
+ // so confusing, it masked unused chunks of code. Also, dividing
+ // between file-based and manifest-based allowed functionaliy
// unused in silverlight to fall out.
- //
+ //
// Note: this type is integral to the construction of exception objects,
// and sometimes this has to be done in low memory situtations (OOM) or
// to create TypeInitializationExceptions due to failure of a static class
- // constructor. This type needs to be extremely careful and assume that
+ // constructor. This type needs to be extremely careful and assume that
// any type it references may have previously failed to construct, so statics
// belonging to that type may not be initialized. FrameworkEventSource.Log
// is one such example.
private bool _useManifest; // Use Assembly manifest, or grovel disk.
- // Whether to fall back to the main assembly or a particular
+ // Whether to fall back to the main assembly or a particular
// satellite for the neutral resources.
private UltimateResourceFallbackLocation _fallbackLoc;
// Version number of satellite assemblies to look for. May be null.
//
//It would be better if we could use _neutralCulture instead of calling
- //CultureInfo.InvariantCulture everywhere, but we run into problems with the .cctor. CultureInfo
+ //CultureInfo.InvariantCulture everywhere, but we run into problems with the .cctor. CultureInfo
//initializes assembly, which initializes ResourceManager, which tries to get a CultureInfo which isn't
//there yet because CultureInfo's class initializer hasn't finished. If we move SystemResMgr off of
//Assembly (or at least make it an internal property) we should be able to circumvent this problem.
BaseNameField = string.Empty;
}
- // Constructs a Resource Manager for files beginning with
+ // Constructs a Resource Manager for files beginning with
// baseName in the directory specified by resourceDir
- // or in the current directory. This Assembly-ignorant constructor is
+ // or in the current directory. This Assembly-ignorant constructor is
// mostly useful for testing your own ResourceSet implementation.
//
- // A good example of a baseName might be "Strings". BaseName
+ // A good example of a baseName might be "Strings". BaseName
// should not end in ".resources".
//
// Note: System.Windows.Forms uses this method at design time.
- //
+ //
private ResourceManager(string baseName, string resourceDir, Type? userResourceSet)
{
if (null == baseName)
set { _fallbackLoc = value; }
}
- // Tells the ResourceManager to call Close on all ResourceSets and
+ // Tells the ResourceManager to call Close on all ResourceSets and
// release all resources. This will shrink your working set by
// potentially a substantial amount in a running application. Any
- // future resource lookups on this ResourceManager will be as
+ // future resource lookups on this ResourceManager will be as
// expensive as the very first lookup, since it will need to search
// for files and load resources again.
- //
- // This may be useful in some complex threading scenarios, where
+ //
+ // This may be useful in some complex threading scenarios, where
// creating a new ResourceManager isn't quite the correct behavior.
public virtual void ReleaseAllResources()
{
return new ResourceManager(baseName, resourceDir, usingResourceSet);
}
- // Given a CultureInfo, GetResourceFileName generates the name for
- // the binary file for the given CultureInfo. This method uses
+ // Given a CultureInfo, GetResourceFileName generates the name for
+ // the binary file for the given CultureInfo. This method uses
// CultureInfo's Name property as part of the file name for all cultures
- // other than the invariant culture. This method does not touch the disk,
+ // other than the invariant culture. This method does not touch the disk,
// and is used only to construct what a resource file name (suitable for
// passing to the ResourceReader constructor) or a manifest resource file
// name should look like.
- //
+ //
// This method can be overriden to look for a different extension,
// such as ".ResX", or a completely different format for naming files.
protected virtual string GetResourceFileName(CultureInfo culture)
}
// Looks up a set of resources for a particular CultureInfo. This is
- // not useful for most users of the ResourceManager - call
- // GetString() or GetObject() instead.
+ // not useful for most users of the ResourceManager - call
+ // GetString() or GetObject() instead.
//
- // The parameters let you control whether the ResourceSet is created
- // if it hasn't yet been loaded and if parent CultureInfos should be
+ // The parameters let you control whether the ResourceSet is created
+ // if it hasn't yet been loaded and if parent CultureInfos should be
// loaded as well for resource inheritance.
- //
+ //
public virtual ResourceSet? GetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents)
{
if (null == culture)
// InternalGetResourceSet is a non-threadsafe method where all the logic
// for getting a resource set lives. Access to it is controlled by
- // threadsafe methods such as GetResourceSet, GetString, & GetObject.
+ // threadsafe methods such as GetResourceSet, GetString, & GetObject.
// This will take a minimal number of locks.
protected virtual ResourceSet? InternalGetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents)
{
// InternalGetResourceSet will never be threadsafe. However, it must
// be protected against reentrancy from the SAME THREAD. (ie, calling
// GetSatelliteAssembly may send some window messages or trigger the
- // Assembly load event, which could fail then call back into the
+ // Assembly load event, which could fail then call back into the
// ResourceManager). It's happened.
rs = _resourceGroveler.GrovelForResourceSet(currentCultureInfo, localResourceSets,
// Simple helper to ease maintenance and improve readability.
private static void AddResourceSet(Dictionary<string, ResourceSet> localResourceSets, string cultureName, ref ResourceSet rs)
{
- // InternalGetResourceSet is both recursive and reentrant -
+ // InternalGetResourceSet is both recursive and reentrant -
// assembly load callbacks in particular are a way we can call
// back into the ResourceManager in unexpectedly on the same thread.
lock (localResourceSets)
{
// Note: In certain cases, we can be trying to add a ResourceSet for multiple
// cultures on one thread, while a second thread added another ResourceSet for one
- // of those cultures. If there is a race condition we must make sure our ResourceSet
+ // of those cultures. If there is a race condition we must make sure our ResourceSet
// isn't in our dictionary before closing it.
if (!localResourceSets.ContainsValue(rs))
rs.Dispose();
return string.Equals(an.Name, "mscorlib", StringComparison.OrdinalIgnoreCase);
}
- // Looks up a resource value for a particular name. Looks in the
+ // Looks up a resource value for a particular name. Looks in the
// current thread's CultureInfo, and if not found, all parent CultureInfos.
// Returns null if the resource wasn't found.
- //
+ //
public virtual string? GetString(string name)
{
return GetString(name, null);
}
- // Looks up a resource value for a particular name. Looks in the
+ // Looks up a resource value for a particular name. Looks in the
// specified CultureInfo, and if not found, all parent CultureInfos.
// Returns null if the resource wasn't found.
- //
+ //
public virtual string? GetString(string name, CultureInfo? culture)
{
if (null == name)
return value;
}
- // This is the CultureInfo hierarchy traversal code for resource
- // lookups, similar but necessarily orthogonal to the ResourceSet
+ // This is the CultureInfo hierarchy traversal code for resource
+ // lookups, similar but necessarily orthogonal to the ResourceSet
// lookup logic.
ResourceFallbackManager mgr = new ResourceFallbackManager(culture, _neutralResourcesCulture, true);
foreach (CultureInfo currentCultureInfo in mgr)
return null;
}
- // Looks up a resource value for a particular name. Looks in the
+ // Looks up a resource value for a particular name. Looks in the
// current thread's CultureInfo, and if not found, all parent CultureInfos.
// Returns null if the resource wasn't found.
- //
+ //
public virtual object? GetObject(string name)
{
return GetObject(name, null, true);
}
- // Looks up a resource value for a particular name. Looks in the
+ // Looks up a resource value for a particular name. Looks in the
// specified CultureInfo, and if not found, all parent CultureInfos.
// Returns null if the resource wasn't found.
public virtual object? GetObject(string name, CultureInfo? culture)
}
}
- // This is the CultureInfo hierarchy traversal code for resource
- // lookups, similar but necessarily orthogonal to the ResourceSet
+ // This is the CultureInfo hierarchy traversal code for resource
+ // lookups, similar but necessarily orthogonal to the ResourceSet
// lookup logic.
ResourceFallbackManager mgr = new ResourceFallbackManager(culture, _neutralResourcesCulture, true);
/*============================================================
**
**
-**
+**
**
**
** Purpose: Culture-specific collection of resources.
**
-**
+**
===========================================================*/
using System.Collections;
namespace System.Resources
{
// A ResourceSet stores all the resources defined in one particular CultureInfo.
- //
+ //
// The method used to load resources is straightforward - this class
- // enumerates over an IResourceReader, loading every name and value, and
+ // enumerates over an IResourceReader, loading every name and value, and
// stores them in a hash table. Custom IResourceReaders can be used.
//
public class ResourceSet : IDisposable, IEnumerable
Table = new Hashtable();
}
- // For RuntimeResourceSet, ignore the Table parameter - it's a wasted
+ // For RuntimeResourceSet, ignore the Table parameter - it's a wasted
// allocation.
internal ResourceSet(bool junk)
{
}
// Creates a ResourceSet using the system default ResourceReader
- // implementation. Use this constructor to open & read from a file
+ // implementation. Use this constructor to open & read from a file
// on disk.
- //
+ //
public ResourceSet(string fileName)
: this()
{
}
// Creates a ResourceSet using the system default ResourceReader
- // implementation. Use this constructor to read from an open stream
+ // implementation. Use this constructor to read from an open stream
// of data.
- //
+ //
public ResourceSet(Stream stream)
: this()
{
}
// Closes and releases any resources used by this ResourceSet, if any.
- // All calls to methods on the ResourceSet after a call to close may
- // fail. Close is guaranteed to be safely callable multiple times on a
+ // All calls to methods on the ResourceSet after a call to close may
+ // fail. Close is guaranteed to be safely callable multiple times on a
// particular ResourceSet, and all subclasses must support these semantics.
public virtual void Close()
{
}
// Look up a string value for a resource given its name.
- //
+ //
public virtual string? GetString(string name)
{
object? obj = GetObjectInternal(name);
}
// Look up an object value for a resource given its name.
- //
+ //
public virtual object? GetObject(string name)
{
return GetObjectInternal(name);
/*============================================================
**
-**
-**
+**
+**
**
**
** Purpose: Marker for types in .resources files
**
-**
+**
===========================================================*/
namespace System.Resources
{
/* An internal implementation detail for .resources files, describing
- what type an object is.
+ what type an object is.
Ranges:
0 - 0x1F Primitives and reserved values
0x20 - 0x3F Specially recognized types, like byte[] and Streams
/*============================================================
**
-**
-**
+**
+**
**
**
** Purpose: CultureInfo-specific collection of resources.
**
-**
+**
===========================================================*/
#nullable enable
#if RESOURCES_EXTENSIONS
using ResourceReader = DeserializingResourceReader;
#endif
- // A RuntimeResourceSet stores all the resources defined in one
+ // A RuntimeResourceSet stores all the resources defined in one
// particular CultureInfo, with some loading optimizations.
//
// It is expected that nearly all the runtime's users will be satisfied with the
// default resource file format, and it will be more efficient than most simple
// implementations. Users who would consider creating their own ResourceSets and/or
- // ResourceReaders and ResourceWriters are people who have to interop with a
- // legacy resource file format, are creating their own resource file format
- // (using XML, for instance), or require doing resource lookups at runtime over
- // the network. This group will hopefully be small, but all the infrastructure
+ // ResourceReaders and ResourceWriters are people who have to interop with a
+ // legacy resource file format, are creating their own resource file format
+ // (using XML, for instance), or require doing resource lookups at runtime over
+ // the network. This group will hopefully be small, but all the infrastructure
// should be in place to let these users write & plug in their own tools.
//
// The Default Resource File Format
//
// The fundamental problems addressed by the resource file format are:
//
- // * Versioning - A ResourceReader could in theory support many different
+ // * Versioning - A ResourceReader could in theory support many different
// file format revisions.
// * Storing intrinsic datatypes (ie, ints, Strings, DateTimes, etc) in a compact
// format
// * Support for user-defined classes - Accomplished using Serialization
- // * Resource lookups should not require loading an entire resource file - If you
+ // * Resource lookups should not require loading an entire resource file - If you
// look up a resource, we only load the value for that resource, minimizing working set.
- //
- //
+ //
+ //
// There are four sections to the default file format. The first
// is the Resource Manager header, which consists of a magic number
// that identifies this as a Resource file, and a ResourceSet class name.
- // The class name is written here to allow users to provide their own
- // implementation of a ResourceSet (and a matching ResourceReader) to
+ // The class name is written here to allow users to provide their own
+ // implementation of a ResourceSet (and a matching ResourceReader) to
// control policy. If objects greater than a certain size or matching a
// certain naming scheme shouldn't be stored in memory, users can tweak that
// with their own subclass of ResourceSet.
- //
- // The second section in the system default file format is the
+ //
+ // The second section in the system default file format is the
// RuntimeResourceSet specific header. This contains a version number for
- // the .resources file, the number of resources in this file, the number of
- // different types contained in the file, followed by a list of fully
+ // the .resources file, the number of resources in this file, the number of
+ // different types contained in the file, followed by a list of fully
// qualified type names. After this, we include an array of hash values for
// each resource name, then an array of virtual offsets into the name section
- // of the file. The hashes allow us to do a binary search on an array of
+ // of the file. The hashes allow us to do a binary search on an array of
// integers to find a resource name very quickly without doing many string
// compares (except for once we find the real type, of course). If a hash
// matches, the index into the array of hash values is used as the index
// into the name position array to find the name of the resource. The type
- // table allows us to read multiple different classes from the same file,
- // including user-defined types, in a more efficient way than using
- // Serialization, at least when your .resources file contains a reasonable
- // proportion of base data types such as Strings or ints. We use
+ // table allows us to read multiple different classes from the same file,
+ // including user-defined types, in a more efficient way than using
+ // Serialization, at least when your .resources file contains a reasonable
+ // proportion of base data types such as Strings or ints. We use
// Serialization for all the non-instrinsic types.
- //
- // The third section of the file is the name section. It contains a
+ //
+ // The third section of the file is the name section. It contains a
// series of resource names, written out as byte-length prefixed little
// endian Unicode strings (UTF-16). After each name is a four byte virtual
- // offset into the data section of the file, pointing to the relevant
+ // offset into the data section of the file, pointing to the relevant
// string or serialized blob for this resource name.
//
// The fourth section in the file is the data section, which consists
- // of a type and a blob of bytes for each item in the file. The type is
+ // of a type and a blob of bytes for each item in the file. The type is
// an integer index into the type table. The data is specific to that type,
- // but may be a number written in binary format, a String, or a serialized
+ // but may be a number written in binary format, a String, or a serialized
// Object.
- //
+ //
// The system default file format (V1) is as follows:
- //
+ //
// What Type of Data
// ==================================================== ===========
//
//
// RuntimeResourceReader Data Section
// Type and Value of each resource Set of (Int32, blob of bytes) pairs
- //
+ //
// This implementation, when used with the default ResourceReader class,
// loads only the strings that you look up for. It can do string comparisons
- // without having to create a new String instance due to some memory mapped
- // file optimizations in the ResourceReader and FastResourceComparer
- // classes. This keeps the memory we touch to a minimum when loading
- // resources.
+ // without having to create a new String instance due to some memory mapped
+ // file optimizations in the ResourceReader and FastResourceComparer
+ // classes. This keeps the memory we touch to a minimum when loading
+ // resources.
//
// If you use a different IResourceReader class to read a file, or if you
// do case-insensitive lookups (and the case-sensitive lookup fails) then
// we will load all the names of each resource and each resource value.
// This could probably use some optimization.
- //
+ //
// In addition, this supports object serialization in a similar fashion.
// We build an array of class types contained in this file, and write it
// to RuntimeResourceReader header section of the file. Every resource
// will contain its type (as an index into the array of classes) with the data
// for that resource. We will use the Runtime's serialization support for this.
- //
+ //
// All strings in the file format are written with BinaryReader and
- // BinaryWriter, which writes out the length of the String in bytes as an
+ // BinaryWriter, which writes out the length of the String in bytes as an
// Int32 then the contents as Unicode chars encoded in UTF-8. In the name
// table though, each resource name is written in UTF-16 so we can do a
// string compare byte by byte against the contents of the file, without
- // allocating objects. Ideally we'd have a way of comparing UTF-8 bytes
+ // allocating objects. Ideally we'd have a way of comparing UTF-8 bytes
// directly against a String object, but that may be a lot of work.
- //
- // The offsets of each resource string are relative to the beginning
- // of the Data section of the file. This way, if a tool decided to add
- // one resource to a file, it would only need to increment the number of
+ //
+ // The offsets of each resource string are relative to the beginning
+ // of the Data section of the file. This way, if a tool decided to add
+ // one resource to a file, it would only need to increment the number of
// resources, add the hash & location of last byte in the name section
// to the array of resource hashes and resource name positions (carefully
- // keeping these arrays sorted), add the name to the end of the name &
- // offset list, possibly add the type list of types (and increase
- // the number of items in the type table), and add the resource value at
- // the end of the file. The other offsets wouldn't need to be updated to
+ // keeping these arrays sorted), add the name to the end of the name &
+ // offset list, possibly add the type list of types (and increase
+ // the number of items in the type table), and add the resource value at
+ // the end of the file. The other offsets wouldn't need to be updated to
// reflect the longer header section.
- //
- // Resource files are currently limited to 2 gigabytes due to these
+ //
+ // Resource files are currently limited to 2 gigabytes due to these
// design parameters. A future version may raise the limit to 4 gigabytes
- // by using unsigned integers, or may use negative numbers to load items
+ // by using unsigned integers, or may use negative numbers to load items
// out of an assembly manifest. Also, we may try sectioning the resource names
// into smaller chunks, each of size sqrt(n), would be substantially better for
// resource files containing thousands of resources.
- //
+ //
#if CORERT
public // On CoreRT, this must be public because of need to whitelist past the ReflectionBlock.
#else
private Dictionary<string, ResourceLocator>? _resCache; // TODO-NULLABLE: Avoid nulling out in Dispose
- // For our special load-on-demand reader, cache the cast. The
+ // For our special load-on-demand reader, cache the cast. The
// RuntimeResourceSet's implementation knows how to treat this reader specially.
private ResourceReader? _defaultReader; // TODO-NULLABLE: Avoid nulling out in Dispose
// This is a lookup table for case-insensitive lookups, and may be null.
// Consider always using a case-insensitive resource cache, as we don't
// want to fill this out if we can avoid it. The problem is resource
- // fallback will somewhat regularly cause us to look up resources that
+ // fallback will somewhat regularly cause us to look up resources that
// don't exist.
private Dictionary<string, ResourceLocator>? _caseInsensitiveTable;
_defaultReader = reader as DeserializingResourceReader ?? throw new ArgumentException(SR.Format(SR.NotSupported_WrongResourceReader_Type, reader.GetType()), nameof(reader));
_resCache = new Dictionary<string, ResourceLocator>(FastResourceComparer.Default);
-
- // in the CoreLib version RuntimeResourceSet creates ResourceReader and passes this in,
+
+ // in the CoreLib version RuntimeResourceSet creates ResourceReader and passes this in,
// in the custom case ManifestBasedResourceReader creates the ResourceReader and passes it in
// so we must initialize the cache here.
_defaultReader._resCache = _resCache;
Debug.Assert(dataPos >= 0, "data section offset cannot be negative!");
// Normally calling LoadString or LoadObject requires
// taking a lock. Note that in this case, we took a
- // lock on the entire RuntimeResourceSet, which is
+ // lock on the entire RuntimeResourceSet, which is
// sufficient since we never pass this ResourceReader
// to anyone else.
ResourceTypeCode typeCode;
} // lock(Reader)
}
- // The last parameter indicates whether the lookup required a
- // case-insensitive lookup to succeed, indicating we shouldn't add
+ // The last parameter indicates whether the lookup required a
+ // case-insensitive lookup to succeed, indicating we shouldn't add
// the ResourceLocation to our case-sensitive cache.
private object? ResolveResourceLocator(ResourceLocator resLocation, string key, Dictionary<string, ResourceLocator> copyOfCache, bool keyInWrongCase)
{
/*============================================================
**
-**
-**
**
**
-** Purpose: Specifies which version of a satellite assembly
+**
+**
+** Purpose: Specifies which version of a satellite assembly
** the ResourceManager should ask for.
**
**
public static AsyncIteratorMethodBuilder Create() =>
// _methodBuilder should be initialized to AsyncTaskMethodBuilder.Create(), but on coreclr
// that Create() is a nop, so we can just return the default here.
- default;
+ default;
/// <summary>Invokes <see cref="IAsyncStateMachine.MoveNext"/> on the state machine while guarding the <see cref="ExecutionContext"/>.</summary>
/// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
if (_synchronizationContext != null)
{
- // If we captured a synchronization context, Post the throwing of the exception to it
+ // If we captured a synchronization context, Post the throwing of the exception to it
// and decrement its outstanding operation count.
try
{
/// Gets an object that may be used to uniquely identify this builder to the debugger.
/// </summary>
/// <remarks>
- /// This property lazily instantiates the ID in a non-thread-safe manner.
+ /// This property lazily instantiates the ID in a non-thread-safe manner.
/// It must only be used by the debugger and AsyncCausalityTracer in a single-threaded manner.
/// </remarks>
internal object ObjectIdForDebugger => _builder.ObjectIdForDebugger;
}
/// <summary>
- /// Completes the <see cref="System.Threading.Tasks.Task"/> in the
+ /// Completes the <see cref="System.Threading.Tasks.Task"/> in the
/// <see cref="System.Threading.Tasks.TaskStatus">RanToCompletion</see> state.
/// </summary>
/// <exception cref="System.InvalidOperationException">The builder is not initialized.</exception>
public void SetResult() => m_builder.SetResult(s_cachedCompleted); // Using s_cachedCompleted is faster than using s_defaultResultTask.
/// <summary>
- /// Completes the <see cref="System.Threading.Tasks.Task"/> in the
+ /// Completes the <see cref="System.Threading.Tasks.Task"/> in the
/// <see cref="System.Threading.Tasks.TaskStatus">Faulted</see> state with the specified exception.
/// </summary>
/// <param name="exception">The <see cref="System.Exception"/> to use to fault the task.</param>
/// Gets an object that may be used to uniquely identify this builder to the debugger.
/// </summary>
/// <remarks>
- /// This property lazily instantiates the ID in a non-thread-safe manner.
+ /// This property lazily instantiates the ID in a non-thread-safe manner.
/// It must only be used by the debugger and tracing purposes, and only in a single-threaded manner
/// when no other threads are in the middle of accessing this property or this.Task.
/// </remarks>
}
/// <summary>
- /// Completes the <see cref="System.Threading.Tasks.Task{TResult}"/> in the
+ /// Completes the <see cref="System.Threading.Tasks.Task{TResult}"/> in the
/// <see cref="System.Threading.Tasks.TaskStatus">RanToCompletion</see> state with the specified result.
/// </summary>
/// <param name="result">The result to use to complete the task.</param>
}
/// <summary>
- /// Completes the <see cref="System.Threading.Tasks.Task{TResult}"/> in the
+ /// Completes the <see cref="System.Threading.Tasks.Task{TResult}"/> in the
/// <see cref="System.Threading.Tasks.TaskStatus">Faulted</see> state with the specified exception.
/// </summary>
/// <param name="exception">The <see cref="System.Exception"/> to use to fault the task.</param>
// Unlike with TaskCompletionSource, we do not need to spin here until _taskAndStateMachine is completed,
// since AsyncTaskMethodBuilder.SetException should not be immediately followed by any code
- // that depends on the task having completely completed. Moreover, with correct usage,
+ // that depends on the task having completely completed. Moreover, with correct usage,
// SetResult or SetException should only be called once, so the Try* methods should always
// return true, so no spinning would be necessary anyway (the spinning in TCS is only relevant
// if another thread completes the task first).
/// Gets an object that may be used to uniquely identify this builder to the debugger.
/// </summary>
/// <remarks>
- /// This property lazily instantiates the ID in a non-thread-safe manner.
+ /// This property lazily instantiates the ID in a non-thread-safe manner.
/// It must only be used by the debugger and tracing purposes, and only in a single-threaded manner
/// when no other threads are in the middle of accessing this or other members that lazily initialize the task.
/// </remarks>
// we need to be able to evaluate the incoming result value, and we need
// to avoid as much overhead as possible when doing so, as this function
// is invoked as part of the return path from every async method.
- // Most tasks won't be cached, and thus we need the checks for those that are
- // to be as close to free as possible. This requires some trickiness given the
+ // Most tasks won't be cached, and thus we need the checks for those that are
+ // to be as close to free as possible. This requires some trickiness given the
// lack of generic specialization in .NET.
//
// Be very careful when modifying this code. It has been tuned
// small tweaks can have big consequences for what does and doesn't get optimized away.
//
// Note that this code only ever accesses a static field when it knows it'll
- // find a cached value, since static fields (even if readonly and integral types)
+ // find a cached value, since static fields (even if readonly and integral types)
// require special access helpers in this NGEN'd and domain-neutral.
if (null != (object)default(TResult)!) // help the JIT avoid the value type branches for ref types // TODO-NULLABLE: default(T) == null warning (https://github.com/dotnet/roslyn/issues/34757)
else if (typeof(TResult) == typeof(int))
{
// Compare to constants to avoid static field access if outside of cached range.
- // We compare to the upper bound first, as we're more likely to cache miss on the upper side than on the
+ // We compare to the upper bound first, as we're more likely to cache miss on the upper side than on the
// lower side, due to positive values being more common than negative as return values.
int value = (int)(object)result!;
if (value < AsyncTaskCache.EXCLUSIVE_INT32_MAX &&
/// <summary>
/// Logically we pass just an Action (delegate) to a task for its action to 'ContinueWith' when it completes.
- /// However debuggers and profilers need more information about what that action is. (In particular what
- /// the action after that is and after that. To solve this problem we create a 'ContinuationWrapper
+ /// However debuggers and profilers need more information about what that action is. (In particular what
+ /// the action after that is and after that. To solve this problem we create a 'ContinuationWrapper
/// which when invoked just does the original action (the invoke action), but also remembers other information
- /// (like the action after that (which is also a ContinuationWrapper and thus form a linked list).
- /// We also store that task if the action is associate with at task.
+ /// (like the action after that (which is also a ContinuationWrapper and thus form a linked list).
+ /// We also store that task if the action is associate with at task.
/// </summary>
private sealed class ContinuationWrapper // SOS DumpAsync command depends on this name
{
- private readonly Action<Action, Task> _invokeAction; // This wrapper is an action that wraps another action, this is that Action.
+ private readonly Action<Action, Task> _invokeAction; // This wrapper is an action that wraps another action, this is that Action.
internal readonly Action _continuation; // This is continuation which will happen after m_invokeAction (and is probably a ContinuationWrapper). SOS DumpAsync command depends on this name.
internal readonly Task _innerTask; // If the continuation is logically going to invoke a task, this is that task (may be null)
/// <param name="awaiter">the awaiter</param>
/// <param name="stateMachine">The state machine.</param>
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
- where TAwaiter : ICriticalNotifyCompletion
+ where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine
{
_useBuilder = true;
namespace System.Runtime.CompilerServices
{
// Attribute used to communicate to the VS7 debugger that a class should be treated as if it has global scope.
-
+
[AttributeUsage(AttributeTargets.Class)]
public class CompilerGlobalScopeAttribute : Attribute
{
public CompilerGlobalScopeAttribute() { }
}
}
-
private TValue GetValueLocked(TKey key, CreateValueCallback createValueCallback)
{
// If we got here, the key was not in the table. Invoke the callback (outside the lock)
- // to generate the new value for the key.
+ // to generate the new value for the key.
TValue newValue = createValueCallback(key);
lock (_lock)
// - Used with live key (linked into a bucket list where _buckets[hashCode & (_buckets.Length - 1)] points to first entry)
// depHnd.IsAllocated == true, depHnd.GetPrimary() != null
// hashCode == RuntimeHelpers.GetHashCode(depHnd.GetPrimary()) & int.MaxValue
- // next links to next Entry in bucket.
- //
+ // next links to next Entry in bucket.
+ //
// - Used with dead key (linked into a bucket list where _buckets[hashCode & (_buckets.Length - 1)] points to first entry)
// depHnd.IsAllocated == true, depHnd.GetPrimary() is null
- // hashCode == <notcare>
- // next links to next Entry in bucket.
+ // hashCode == <notcare>
+ // next links to next Entry in bucket.
//
// - Has been removed from the table (by a call to Remove)
// depHnd.IsAllocated == true, depHnd.GetPrimary() == <notcare>
- // hashCode == -1
- // next links to next Entry in bucket.
+ // hashCode == -1
+ // next links to next Entry in bucket.
//
// The only difference between "used with live key" and "used with dead key" is that
// depHnd.GetPrimary() returns null. The transition from "used with live key" to "used with dead key"
{
/// <summary>
/// Allows a managed application environment such as an interactive interpreter (IronPython) or a
- /// web browser host (Jolt hosting Silverlight in IE) to be notified of contract failures and
+ /// web browser host (Jolt hosting Silverlight in IE) to be notified of contract failures and
/// potentially "handle" them, either by throwing a particular exception type, etc. If any of the
/// event handlers sets the Cancel flag in the ContractFailedEventArgs, then the Contract class will
/// not pop up an assert dialog box or trigger escalation policy.
{
string failureMessage;
// Well-formatted English messages will take one of four forms. A sentence ending in
- // either a period or a colon, the condition string, then the message tacked
+ // either a period or a colon, the condition string, then the message tacked
// on to the end with two spaces in front.
- // Note that both the conditionText and userMessage may be null. Also,
+ // Note that both the conditionText and userMessage may be null. Also,
// on Silverlight we may not be able to look up a friendly string for the
- // error message. Let's leverage Silverlight's default error message there.
+ // error message. Let's leverage Silverlight's default error message there.
if (!string.IsNullOrEmpty(conditionText))
{
failureMessage = GetFailureMessage(failureKind, conditionText);
public DisablePrivateReflectionAttribute() { }
}
}
-
namespace System.Runtime.CompilerServices
{
// Custom attribute to indicating a TypeDef is a discardable attribute.
-
+
public class DiscardableAttribute : Attribute
{
public DiscardableAttribute() { }
public bool AllInternalsVisible { get; set; } = true;
}
}
-
// no instantiation, please!
}
}
-
namespace System.Runtime.CompilerServices
{
- // This Enum matchs the miImpl flags defined in corhdr.h. It is used to specify
+ // This Enum matchs the miImpl flags defined in corhdr.h. It is used to specify
// certain method properties.
[Flags]
public enum MethodImplOptions
**
** Attribute: ReferenceAssemblyAttribute
**
-** Purpose: Identifies an assembly as being a "reference
+** Purpose: Identifies an assembly as being a "reference
** assembly", meaning it contains public surface area but
-** no usable implementation. Reference assemblies
+** no usable implementation. Reference assemblies
** should be loadable for introspection, but not execution.
**
============================================================*/
namespace System.Runtime.CompilerServices
{
// Custom attribute to indicate that strings should be frozen.
-
+
[AttributeUsage(AttributeTargets.Assembly, Inherited = false)]
public sealed class StringFreezingAttribute : Attribute
{
public SuppressIldasmAttribute() { }
}
}
-
//
//
//
-// Types for awaiting Task and Task<T>. These types are emitted from Task{<T>}.GetAwaiter
+// Types for awaiting Task and Task<T>. These types are emitted from Task{<T>}.GetAwaiter
// and Task{<T>}.ConfigureAwait. They are meant to be used only by the compiler, e.g.
-//
+//
// await nonGenericTask;
// =====================
// var $awaiter = nonGenericTask.GetAwaiter();
}
/// <summary>
- /// Ensures the task is completed, triggers any necessary debugger breakpoints for completing
+ /// Ensures the task is completed, triggers any necessary debugger breakpoints for completing
/// the await on the task, and throws an exception if the task did not complete successfully.
/// </summary>
/// <param name="task">The awaited task.</param>
// Its layout must remain the same.
/// <summary>The task being awaited.</summary>
- internal readonly Task m_task;
+ internal readonly Task m_task;
/// <summary>Whether to attempt marshaling back to the original context.</summary>
- internal readonly bool m_continueOnCapturedContext;
+ internal readonly bool m_continueOnCapturedContext;
/// <summary>Initializes the <see cref="ConfiguredTaskAwaiter"/>.</summary>
/// <param name="task">The <see cref="System.Threading.Tasks.Task"/> to await.</param>
//
//
// Compiler-targeted type for switching back into the current execution context, e.g.
-//
+//
// await Task.Yield();
// =====================
// var $awaiter = Task.Yield().GetAwaiter();
** (i.e. the finalizer is guaranteed to run, won't be aborted by the host and is
** run after the finalizers of other objects collected at the same time).
**
-**
+**
===========================================================*/
namespace System.Runtime.ConstrainedExecution
**
**
**
-** Purpose: Defines a publically documentable contract for
+** Purpose: Defines a publically documentable contract for
** reliability between a method and its callers, expressing
-** what state will remain consistent in the presence of
+** what state will remain consistent in the presence of
** failures (ie async exceptions like thread abort) and whether
** the method needs to be called from within a CER.
**
// object. This allows us to track error (via the exception object) independent
// of the path the error takes.
//
- // This is particularly useful for frameworks that wish to propagate
+ // This is particularly useful for frameworks that wish to propagate
// exceptions (i.e. errors to be precise) across threads.
public sealed class ExceptionDispatchInfo
{
namespace System.Runtime.InteropServices
{
- // Use this in P/Invoke function prototypes to specify
+ // Use this in P/Invoke function prototypes to specify
// which character set to use when marshalling Strings.
// Using Ansi will marshal the strings as 1 byte char*'s.
// Using Unicode will marshal the strings as 2 byte wchar*'s.
public enum CharSet
{
None = 1, // User didn't specify how to marshal strings.
- Ansi = 2, // Strings should be marshalled as ANSI 1 byte chars.
+ Ansi = 2, // Strings should be marshalled as ANSI 1 byte chars.
Unicode = 3, // Strings should be marshalled as Unicode 2 byte chars.
- Auto = 4, // Marshal Strings in the right way for the target system.
+ Auto = 4, // Marshal Strings in the right way for the target system.
}
}
** progress). The runtime cannot protect you from undefined program
** behvior that might result from such scenarios. You have been warned.
**
-**
+**
===========================================================*/
using System.Runtime.ConstrainedExecution;
Most classes using CriticalHandle should not provide a finalizer. If they do
need to do so (ie, for flushing out file buffers, needing to write some data
- back into memory, etc), then they can provide a finalizer that will be
+ back into memory, etc), then they can provide a finalizer that will be
guaranteed to run before the CriticalHandle's critical finalizer.
Subclasses are expected to be written as follows:
{
// ! Do not add or rearrange fields as the EE depends on this layout.
//------------------------------------------------------------------
- protected IntPtr handle; // This must be protected so derived classes can use out params.
+ protected IntPtr handle; // This must be protected so derived classes can use out params.
private bool _isClosed; // Set by SetHandleAsInvalid or Close/Dispose/finalization.
// Creates a CriticalHandle class. Users must then set the Handle property or allow P/Invoke marshaling to set it implicitly.
**
**
**
-** Purpose: Exception base class for all errors from Interop or Structured
+** Purpose: Exception base class for all errors from Interop or Structured
** Exception Handling code.
**
**
namespace System.Runtime.InteropServices
{
- // These are the types of handles used by the EE.
- // IMPORTANT: These must match the definitions in ObjectHandle.h in the EE.
+ // These are the types of handles used by the EE.
+ // IMPORTANT: These must match the definitions in ObjectHandle.h in the EE.
// IMPORTANT: If new values are added to the enum the GCHandle.MaxHandleType
// constant must be updated.
public enum GCHandleType
}
return (IntPtr)(-1);
- }
+ }
public static IntPtr GetIUnknownForObject(object o)
{
throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
}
- public static Type GetTypeFromCLSID(Guid clsid)
+ public static Type GetTypeFromCLSID(Guid clsid)
{
throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
}
}
IntPtr hglobal = AllocHGlobal((IntPtr)nb);
-
+
fixed (char* firstChar = s)
{
string.wstrcpy((char*)hglobal, firstChar, s.Length + 1);
/// <param name="array">The pre-pinned target array.</param>
/// <param name="start">The index at which to begin the memory.</param>
/// <param name="length">The number of items in the memory.</param>
- /// <remarks>This method should only be called on an array that is already pinned and
+ /// <remarks>This method should only be called on an array that is already pinned and
/// that array should not be unpinned while the returned Memory<typeparamref name="T"/> is still in use.
/// Calling this method on an unpinned array could result in memory corruption.</remarks>
/// <remarks>Returns default when <paramref name="array"/> is null.</remarks>
/// <param name="libraryName">The native library to resolve</param>
/// <param name="assembly">The assembly requesting the resolution</param>
/// <param name="searchPath">
- /// The DllImportSearchPathsAttribute on the PInvoke, if any.
- /// Otherwise, the DllImportSearchPathsAttribute on the assembly, if any.
+ /// The DllImportSearchPathsAttribute on the PInvoke, if any.
+ /// Otherwise, the DllImportSearchPathsAttribute on the assembly, if any.
/// Otherwise null.
/// </param>
- /// <returns>The handle for the loaded native library on success, null on failure</returns>
+ /// <returns>The handle for the loaded native library on success, null on failure</returns>
public delegate IntPtr DllImportResolver(string libraryName,
Assembly assembly,
DllImportSearchPath? searchPath);
/// <summary>
- /// APIs for managing Native Libraries
+ /// APIs for managing Native Libraries
/// </summary>
public static partial class NativeLibrary
{
/// This method is a wrapper around OS loader, using "default" flags.
/// </summary>
/// <param name="libraryPath">The name of the native library to be loaded</param>
- /// <returns>The handle for the loaded native library</returns>
+ /// <returns>The handle for the loaded native library</returns>
/// <exception cref="System.ArgumentNullException">If libraryPath is null</exception>
/// <exception cref="System.DllNotFoundException ">If the library can't be found.</exception>
/// <exception cref="System.BadImageFormatException">If the library is not valid.</exception>
/// </summary>
/// <param name="libraryPath">The name of the native library to be loaded</param>
/// <param name="handle">The out-parameter for the loaded native library handle</param>
- /// <returns>True on successful load, false otherwise</returns>
+ /// <returns>True on successful load, false otherwise</returns>
/// <exception cref="System.ArgumentNullException">If libraryPath is null</exception>
public static bool TryLoad(string libraryPath, out IntPtr handle)
{
/// <summary>
/// NativeLibrary Loader: High-level API
- /// Given a library name, this function searches specific paths based on the
+ /// Given a library name, this function searches specific paths based on the
/// runtime configuration, input parameters, and attributes of the calling assembly.
/// If DllImportSearchPath parameter is non-null, the flags in this enumeration are used.
- /// Otherwise, the flags specified by the DefaultDllImportSearchPaths attribute on the
- /// calling assembly (if any) are used.
- /// This LoadLibrary() method does not invoke the managed call-backs for native library resolution:
- /// * The per-assembly registered callback
+ /// Otherwise, the flags specified by the DefaultDllImportSearchPaths attribute on the
+ /// calling assembly (if any) are used.
+ /// This LoadLibrary() method does not invoke the managed call-backs for native library resolution:
+ /// * The per-assembly registered callback
/// * AssemblyLoadContext.LoadUnmanagedDll()
/// * AssemblyLoadContext.ResolvingUnmanagedDllEvent
/// </summary>
/// <param name="libraryName">The name of the native library to be loaded</param>
/// <param name="assembly">The assembly loading the native library</param>
/// <param name="searchPath">The search path</param>
- /// <returns>The handle for the loaded library</returns>
+ /// <returns>The handle for the loaded library</returns>
/// <exception cref="System.ArgumentNullException">If libraryPath or assembly is null</exception>
/// <exception cref="System.ArgumentException">If assembly is not a RuntimeAssembly</exception>
/// <exception cref="System.DllNotFoundException ">If the library can't be found.</exception>
- /// <exception cref="System.BadImageFormatException">If the library is not valid.</exception>
+ /// <exception cref="System.BadImageFormatException">If the library is not valid.</exception>
public static IntPtr Load(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
{
if (libraryName == null)
throw new ArgumentNullException(nameof(assembly));
if (!assembly.IsRuntimeImplemented())
throw new ArgumentException(SR.Argument_MustBeRuntimeAssembly);
-
- return LoadLibraryByName(libraryName,
+
+ return LoadLibraryByName(libraryName,
assembly,
searchPath,
throwOnError: true);
/// <param name="searchPath">The search path</param>
/// <param name="assembly">The assembly loading the native library</param>
/// <param name="handle">The out-parameter for the loaded native library handle</param>
- /// <returns>True on successful load, false otherwise</returns>
+ /// <returns>True on successful load, false otherwise</returns>
/// <exception cref="System.ArgumentNullException">If libraryPath or assembly is null</exception>
/// <exception cref="System.ArgumentException">If assembly is not a RuntimeAssembly</exception>
public static bool TryLoad(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle)
throw new ArgumentNullException(nameof(assembly));
if (!assembly.IsRuntimeImplemented())
throw new ArgumentException(SR.Argument_MustBeRuntimeAssembly);
-
+
handle = LoadLibraryByName(libraryName,
assembly,
searchPath,
/// </summary>
/// <param name="handle">The native library handle</param>
/// <param name="name">The name of the exported symbol</param>
- /// <returns>The address of the symbol</returns>
+ /// <returns>The address of the symbol</returns>
/// <exception cref="System.ArgumentNullException">If handle or name is null</exception>
/// <exception cref="System.EntryPointNotFoundException">If the symbol is not found</exception>
public static IntPtr GetExport(IntPtr handle, string name)
{
- if (handle == IntPtr.Zero)
+ if (handle == IntPtr.Zero)
throw new ArgumentNullException(nameof(handle));
if (name == null)
throw new ArgumentNullException(nameof(name));
/// <param name="handle">The native library handle</param>
/// <param name="name">The name of the exported symbol</param>
/// <param name="address"> The out-parameter for the symbol address, if it exists</param>
- /// <returns>True on success, false otherwise</returns>
+ /// <returns>True on success, false otherwise</returns>
/// <exception cref="System.ArgumentNullException">If handle or name is null</exception>
public static bool TryGetExport(IntPtr handle, string name, out IntPtr address)
{
- if (handle == IntPtr.Zero)
+ if (handle == IntPtr.Zero)
throw new ArgumentNullException(nameof(handle));
if (name == null)
throw new ArgumentNullException(nameof(name));
/// <summary>
/// Map from assembly to native-library resolver.
/// Interop specific fields and properties are generally not added to Assembly class.
- /// Therefore, this table uses weak assembly pointers to indirectly achieve
+ /// Therefore, this table uses weak assembly pointers to indirectly achieve
/// similar behavior.
/// </summary>
private static ConditionalWeakTable<Assembly, DllImportResolver>? s_nativeDllResolveMap;
/// <summary>
/// Set a callback for resolving native library imports from an assembly.
- /// This per-assembly resolver is the first attempt to resolve native library loads
+ /// This per-assembly resolver is the first attempt to resolve native library loads
/// initiated by this assembly.
///
- /// Only one resolver can be registered per assembly.
+ /// Only one resolver can be registered per assembly.
/// Trying to register a second resolver fails with InvalidOperationException.
/// </summary>
/// <param name="assembly">The assembly for which the resolver is registered</param>
}
/// <summary>
- /// The helper function that calls the per-assembly native-library resolver
+ /// The helper function that calls the per-assembly native-library resolver
/// if one is registered for this assembly.
/// </summary>
/// <param name="libraryName">The native library to load</param>
/// <param name="assembly">The assembly trying load the native library</param>
/// <param name="hasDllImportSearchPathFlags">If the pInvoke has DefaultDllImportSearchPathAttribute</param>
- /// <param name="dllImportSearchPathFlags">If hasdllImportSearchPathFlags is true, the flags in
+ /// <param name="dllImportSearchPathFlags">If hasdllImportSearchPathFlags is true, the flags in
/// DefaultDllImportSearchPathAttribute; meaningless otherwise </param>
- /// <returns>The handle for the loaded library on success. Null on failure.</returns>
+ /// <returns>The handle for the loaded library on success. Null on failure.</returns>
internal static IntPtr LoadLibraryCallbackStub(string libraryName, Assembly assembly,
bool hasDllImportSearchPathFlags, uint dllImportSearchPathFlags)
{
/// Obtain the pointer from a SafeBuffer for a block of code,
/// with the express responsibility for bounds checking and calling
/// ReleasePointer later to ensure the pointer can be freed later.
- /// This method either completes successfully or throws an exception
+ /// This method either completes successfully or throws an exception
/// and returns with pointer set to null.
/// </summary>
/// <param name="pointer">A byte*, passed by reference, to receive
/// +-----------------------------------------------------------+---+---+
/// | Ref count | D | C |
/// +-----------------------------------------------------------+---+---+
- ///
+ ///
/// Where D = 1 means a Dispose has been performed and C = 1 means the
/// underlying handle has been (or will be shortly) released.
/// </remarks>
// the state moves to closed.
newState = oldState + StateBits.RefCountOne;
} while (Interlocked.CompareExchange(ref _state, newState, oldState) != oldState);
-
+
// If we got here we managed to update the ref count while the state
// remained non closed. So we're done.
success = true;
if (Avx.IsSupported)
{
- Vector128<float> result = Vector128.Create(value); // < v, v, v, v, ?, ?, ?, ? >
+ Vector128<float> result = Vector128.Create(value); // < v, v, v, v, ?, ?, ?, ? >
return Avx.InsertVector128(result.ToVector256Unsafe(), result, 1); // < v, v, v, v, v, v, v, v >
}
/// VPERM2F128 ymm, ymm, ymm/m256, imm8
/// </summary>
public static Vector256<short> Permute2x128(Vector256<short> left, Vector256<short> right, byte control) { throw new PlatformNotSupportedException(); }
-
+
/// <summary>
/// __m256i _mm256_permute2f128_si256 (__m256i a, __m256i b, int imm8)
/// VPERM2F128 ymm, ymm, ymm/m256, imm8
/// VPERM2F128 ymm, ymm, ymm/m256, imm8
/// </summary>
public static Vector256<short> Permute2x128(Vector256<short> left, Vector256<short> right, byte control) => Permute2x128(left, right, control);
-
+
/// <summary>
/// __m256i _mm256_permute2f128_si256 (__m256i a, __m256i b, int imm8)
/// VPERM2F128 ymm, ymm, ymm/m256, imm8
/// <summary>
/// __m128i _mm_broadcastb_epi8 (__m128i a)
/// VPBROADCASTB xmm, m8
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// We provide this additional overload for the lack of pointers to managed.
/// </summary>
public static unsafe Vector128<byte> BroadcastScalarToVector128(byte* source) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m128i _mm_broadcastb_epi8 (__m128i a)
/// VPBROADCASTB xmm, m8
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector128<sbyte> BroadcastScalarToVector128(sbyte* source) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m128i _mm_broadcastw_epi16 (__m128i a)
/// VPBROADCASTW xmm, m16
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector128<short> BroadcastScalarToVector128(short* source) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m128i _mm_broadcastw_epi16 (__m128i a)
/// VPBROADCASTW xmm, m16
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector128<ushort> BroadcastScalarToVector128(ushort* source) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m128i _mm_broadcastd_epi32 (__m128i a)
/// VPBROADCASTD xmm, m32
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector128<int> BroadcastScalarToVector128(int* source) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m128i _mm_broadcastd_epi32 (__m128i a)
/// VPBROADCASTD xmm, m32
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector128<uint> BroadcastScalarToVector128(uint* source) { throw new PlatformNotSupportedException(); }
-
+
/// <summary>
/// __m128i _mm_broadcastq_epi64 (__m128i a)
/// VPBROADCASTQ xmm, m64
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector128<long> BroadcastScalarToVector128(long* source) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m128i _mm_broadcastq_epi64 (__m128i a)
/// VPBROADCASTQ xmm, m64
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector128<ulong> BroadcastScalarToVector128(ulong* source) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m256i _mm256_broadcastb_epi8 (__m128i a)
/// VPBROADCASTB ymm, m8
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<byte> BroadcastScalarToVector256(byte* source) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m256i _mm256_broadcastb_epi8 (__m128i a)
/// VPBROADCASTB ymm, m8
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<sbyte> BroadcastScalarToVector256(sbyte* source) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m256i _mm256_broadcastw_epi16 (__m128i a)
/// VPBROADCASTW ymm, m16
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<short> BroadcastScalarToVector256(short* source) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m256i _mm256_broadcastw_epi16 (__m128i a)
/// VPBROADCASTW ymm, m16
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<ushort> BroadcastScalarToVector256(ushort* source) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m256i _mm256_broadcastd_epi32 (__m128i a)
/// VPBROADCASTD ymm, m32
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<int> BroadcastScalarToVector256(int* source) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m256i _mm256_broadcastd_epi32 (__m128i a)
/// VPBROADCASTD ymm, m32
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<uint> BroadcastScalarToVector256(uint* source) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m256i _mm256_broadcastq_epi64 (__m128i a)
/// VPBROADCASTQ ymm, m64
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<long> BroadcastScalarToVector256(long* source) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m256i _mm256_broadcastq_epi64 (__m128i a)
/// VPBROADCASTQ ymm, m64
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<ulong> BroadcastScalarToVector256(ulong* source) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m256i _mm256_broadcastsi128_si256 (__m128i a)
/// VBROADCASTI128 ymm, m128
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<sbyte> BroadcastVector128ToVector256(sbyte* address) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m256i _mm256_broadcastsi128_si256 (__m128i a)
/// VBROADCASTI128 ymm, m128
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<byte> BroadcastVector128ToVector256(byte* address) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m256i _mm256_broadcastsi128_si256 (__m128i a)
/// VBROADCASTI128 ymm, m128
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<short> BroadcastVector128ToVector256(short* address) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m256i _mm256_broadcastsi128_si256 (__m128i a)
/// VBROADCASTI128 ymm, m128
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<ushort> BroadcastVector128ToVector256(ushort* address) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m256i _mm256_broadcastsi128_si256 (__m128i a)
/// VBROADCASTI128 ymm, m128
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<int> BroadcastVector128ToVector256(int* address) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m256i _mm256_broadcastsi128_si256 (__m128i a)
/// VBROADCASTI128 ymm, m128
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<uint> BroadcastVector128ToVector256(uint* address) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m256i _mm256_broadcastsi128_si256 (__m128i a)
/// VBROADCASTI128 ymm, m128
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<long> BroadcastVector128ToVector256(long* address) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m256i _mm256_broadcastsi128_si256 (__m128i a)
/// VBROADCASTI128 ymm, m128
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<ulong> BroadcastVector128ToVector256(ulong* address) { throw new PlatformNotSupportedException(); }
/// <summary>
/// __m128i _mm_broadcastb_epi8 (__m128i a)
/// VPBROADCASTB xmm, m8
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector128<byte> BroadcastScalarToVector128(byte* source) => BroadcastScalarToVector128(source);
/// <summary>
/// __m128i _mm_broadcastb_epi8 (__m128i a)
/// VPBROADCASTB xmm, m8
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector128<sbyte> BroadcastScalarToVector128(sbyte* source) => BroadcastScalarToVector128(source);
/// <summary>
/// __m128i _mm_broadcastw_epi16 (__m128i a)
/// VPBROADCASTW xmm, m16
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector128<short> BroadcastScalarToVector128(short* source) => BroadcastScalarToVector128(source);
/// <summary>
/// __m128i _mm_broadcastw_epi16 (__m128i a)
/// VPBROADCASTW xmm, m16
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector128<ushort> BroadcastScalarToVector128(ushort* source) => BroadcastScalarToVector128(source);
/// <summary>
/// __m128i _mm_broadcastd_epi32 (__m128i a)
/// VPBROADCASTD xmm, m32
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector128<int> BroadcastScalarToVector128(int* source) => BroadcastScalarToVector128(source);
/// <summary>
/// __m128i _mm_broadcastd_epi32 (__m128i a)
/// VPBROADCASTD xmm, m32
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector128<uint> BroadcastScalarToVector128(uint* source) => BroadcastScalarToVector128(source);
/// <summary>
/// __m128i _mm_broadcastq_epi64 (__m128i a)
/// VPBROADCASTQ xmm, m64
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector128<long> BroadcastScalarToVector128(long* source) => BroadcastScalarToVector128(source);
/// <summary>
/// __m128i _mm_broadcastq_epi64 (__m128i a)
/// VPBROADCASTQ xmm, m64
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector128<ulong> BroadcastScalarToVector128(ulong* source) => BroadcastScalarToVector128(source);
/// <summary>
/// __m256i _mm256_broadcastb_epi8 (__m128i a)
/// VPBROADCASTB ymm, m8
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<byte> BroadcastScalarToVector256(byte* source) => BroadcastScalarToVector256(source);
/// <summary>
/// __m256i _mm256_broadcastb_epi8 (__m128i a)
/// VPBROADCASTB ymm, m8
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<sbyte> BroadcastScalarToVector256(sbyte* source) => BroadcastScalarToVector256(source);
/// <summary>
/// __m256i _mm256_broadcastw_epi16 (__m128i a)
/// VPBROADCASTW ymm, m16
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<short> BroadcastScalarToVector256(short* source) => BroadcastScalarToVector256(source);
/// <summary>
/// __m256i _mm256_broadcastw_epi16 (__m128i a)
/// VPBROADCASTW ymm, m16
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<ushort> BroadcastScalarToVector256(ushort* source) => BroadcastScalarToVector256(source);
/// <summary>
/// __m256i _mm256_broadcastd_epi32 (__m128i a)
/// VPBROADCASTD ymm, m32
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<int> BroadcastScalarToVector256(int* source) => BroadcastScalarToVector256(source);
/// <summary>
/// __m256i _mm256_broadcastd_epi32 (__m128i a)
/// VPBROADCASTD ymm, m32
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<uint> BroadcastScalarToVector256(uint* source) => BroadcastScalarToVector256(source);
/// <summary>
/// __m256i _mm256_broadcastq_epi64 (__m128i a)
/// VPBROADCASTQ ymm, m64
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<long> BroadcastScalarToVector256(long* source) => BroadcastScalarToVector256(source);
/// <summary>
/// __m256i _mm256_broadcastq_epi64 (__m128i a)
/// VPBROADCASTQ ymm, m64
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<ulong> BroadcastScalarToVector256(ulong* source) => BroadcastScalarToVector256(source);
/// <summary>
/// __m256i _mm256_broadcastsi128_si256 (__m128i a)
/// VBROADCASTI128 ymm, m128
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<sbyte> BroadcastVector128ToVector256(sbyte* address) => BroadcastVector128ToVector256(address);
/// <summary>
/// __m256i _mm256_broadcastsi128_si256 (__m128i a)
/// VBROADCASTI128 ymm, m128
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<byte> BroadcastVector128ToVector256(byte* address) => BroadcastVector128ToVector256(address);
/// <summary>
/// __m256i _mm256_broadcastsi128_si256 (__m128i a)
/// VBROADCASTI128 ymm, m128
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<short> BroadcastVector128ToVector256(short* address) => BroadcastVector128ToVector256(address);
/// <summary>
/// __m256i _mm256_broadcastsi128_si256 (__m128i a)
/// VBROADCASTI128 ymm, m128
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<ushort> BroadcastVector128ToVector256(ushort* address) => BroadcastVector128ToVector256(address);
/// <summary>
/// __m256i _mm256_broadcastsi128_si256 (__m128i a)
/// VBROADCASTI128 ymm, m128
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<int> BroadcastVector128ToVector256(int* address) => BroadcastVector128ToVector256(address);
/// <summary>
/// __m256i _mm256_broadcastsi128_si256 (__m128i a)
/// VBROADCASTI128 ymm, m128
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<uint> BroadcastVector128ToVector256(uint* address) => BroadcastVector128ToVector256(address);
/// <summary>
/// __m256i _mm256_broadcastsi128_si256 (__m128i a)
/// VBROADCASTI128 ymm, m128
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<long> BroadcastVector128ToVector256(long* address) => BroadcastVector128ToVector256(address);
/// <summary>
/// __m256i _mm256_broadcastsi128_si256 (__m128i a)
/// VBROADCASTI128 ymm, m128
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe Vector256<ulong> BroadcastVector128ToVector256(ulong* address) => BroadcastVector128ToVector256(address);
/// VGATHERQPS xmm, vm64y, xmm
/// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
/// </summary>
- public static unsafe Vector128<float> GatherVector128(float* baseAddress, Vector256<long> index, byte scale)
+ public static unsafe Vector128<float> GatherVector128(float* baseAddress, Vector256<long> index, byte scale)
{
switch (scale)
{
/// <summary>
/// unsigned __int64 _mulx_u64 (unsigned __int64 a, unsigned __int64 b, unsigned __int64* hi)
/// MULX r64a, r64b, reg/m64
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// This intrinisc is only available on 64-bit processes
/// </summary>
public static ulong MultiplyNoFlags(ulong left, ulong right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// unsigned __int64 _mulx_u64 (unsigned __int64 a, unsigned __int64 b, unsigned __int64* hi)
/// MULX r64a, r64b, reg/m64
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// This intrinisc is only available on 64-bit processes
/// </summary>
public static unsafe ulong MultiplyNoFlags(ulong left, ulong right, ulong* low) { throw new PlatformNotSupportedException(); }
/// <summary>
/// unsigned int _mulx_u32 (unsigned int a, unsigned int b, unsigned int* hi)
/// MULX r32a, r32b, reg/m32
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static uint MultiplyNoFlags(uint left, uint right) { throw new PlatformNotSupportedException(); }
/// <summary>
/// unsigned int _mulx_u32 (unsigned int a, unsigned int b, unsigned int* hi)
/// MULX r32a, r32b, reg/m32
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe uint MultiplyNoFlags(uint left, uint right, uint* low) { throw new PlatformNotSupportedException(); }
/// <summary>
/// unsigned __int64 _mulx_u64 (unsigned __int64 a, unsigned __int64 b, unsigned __int64* hi)
/// MULX r64a, r64b, reg/m64
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// This intrinisc is only available on 64-bit processes
/// </summary>
public static ulong MultiplyNoFlags(ulong left, ulong right) => MultiplyNoFlags(left, right);
/// <summary>
/// unsigned __int64 _mulx_u64 (unsigned __int64 a, unsigned __int64 b, unsigned __int64* hi)
/// MULX r64a, r64b, reg/m64
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// This intrinisc is only available on 64-bit processes
/// </summary>
public static unsafe ulong MultiplyNoFlags(ulong left, ulong right, ulong* low) => MultiplyNoFlags(left, right, low);
/// <summary>
/// unsigned int _mulx_u32 (unsigned int a, unsigned int b, unsigned int* hi)
/// MULX r32a, r32b, reg/m32
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static uint MultiplyNoFlags(uint left, uint right) => MultiplyNoFlags(left, right);
/// <summary>
/// unsigned int _mulx_u32 (unsigned int a, unsigned int b, unsigned int* hi)
/// MULX r32a, r32b, reg/m32
- /// The above native signature does not directly correspond to the managed signature.
+ /// The above native signature does not directly correspond to the managed signature.
/// </summary>
public static unsafe uint MultiplyNoFlags(uint left, uint right, uint* low) => MultiplyNoFlags(left, right, low);
/// </summary>
public static ulong Crc32(ulong crc, ulong data) { throw new PlatformNotSupportedException(); }
}
-
+
/// <summary>
/// __m128i _mm_cmpgt_epi64 (__m128i a, __m128i b)
/// PCMPGTQ xmm, xmm/m128
return false;
}
- // Based on the shouldThrow parameter, this will throw an exception, or
+ // Based on the shouldThrow parameter, this will throw an exception, or
// returns whether there is enough space. In all cases, we update
- // our last known free address space, hopefully avoiding needing to
+ // our last known free address space, hopefully avoiding needing to
// probe again.
private static bool CheckForFreeAddressSpace(ulong size, bool shouldThrow)
{
return true;
}
- // Based on the shouldThrow parameter, this will throw an exception, or
+ // Based on the shouldThrow parameter, this will throw an exception, or
// returns whether there is enough space. In all cases, we update
- // our last known free address space, hopefully avoiding needing to
+ // our last known free address space, hopefully avoiding needing to
// probe again.
private static unsafe bool CheckForFreeAddressSpace(ulong size, bool shouldThrow)
{
// Console.WriteLine($"MemoryFailPoint: Checked for free VA space. Found enough? {(freeSpaceAfterGCHeap >= size)} Asked for: {size} Found: {freeSpaceAfterGCHeap}");
// We may set these without taking a lock - I don't believe
- // this will hurt, as long as we never increment this number in
+ // this will hurt, as long as we never increment this number in
// the Dispose method. If we do an extra bit of checking every
// once in a while, but we avoid taking a lock, we may win.
LastKnownFreeAddressSpace = (long)freeSpaceAfterGCHeap;
}
// Returns the amount of consecutive free memory available in a block
- // of pages. If we didn't have enough address space, we still return
- // a positive value < size, to help potentially avoid the overhead of
+ // of pages. If we didn't have enough address space, we still return
+ // a positive value < size, to help potentially avoid the overhead of
// this check if we use a MemoryFailPoint with a smaller size next.
private static unsafe ulong MemFreeAfterAddress(void* address, ulong size)
{
**
**
** Provides a way for an app to not start an operation unless
-** there's a reasonable chance there's enough memory
+** there's a reasonable chance there's enough memory
** available for the operation to succeed.
**
-**
+**
===========================================================*/
using System.Threading;
using System.Runtime.ConstrainedExecution;
using System.Diagnostics;
-/*
- This class allows an application to fail before starting certain
+/*
+ This class allows an application to fail before starting certain
activities. The idea is to fail early instead of failing in the middle
- of some long-running operation to increase the survivability of the
- application and ensure you don't have to write tricky code to handle an
+ of some long-running operation to increase the survivability of the
+ application and ensure you don't have to write tricky code to handle an
OOM anywhere in your app's code (which implies state corruption, meaning you
should unload the appdomain, if you have a transacted environment to ensure
rollback of individual transactions). This is an incomplete tool to attempt
- hoisting all your OOM failures from anywhere in your worker methods to one
+ hoisting all your OOM failures from anywhere in your worker methods to one
particular point where it is easier to handle an OOM failure, and you can
- optionally choose to not start a workitem if it will likely fail. This does
- not help the performance of your code directly (other than helping to avoid
- AD unloads). The point is to avoid starting work if it is likely to fail.
- The Enterprise Services team has used these memory gates effectively in the
+ optionally choose to not start a workitem if it will likely fail. This does
+ not help the performance of your code directly (other than helping to avoid
+ AD unloads). The point is to avoid starting work if it is likely to fail.
+ The Enterprise Services team has used these memory gates effectively in the
unmanaged world for a decade.
In Whidbey, we will simply check to see if there is enough memory available
in the OS's page file & attempt to ensure there might be enough space free
within the process's address space (checking for address space fragmentation
as well). We will not commit or reserve any memory. To avoid race conditions with
- other threads using MemoryFailPoints, we'll also keep track of a
- process-wide amount of memory "reserved" via all currently-active
+ other threads using MemoryFailPoints, we'll also keep track of a
+ process-wide amount of memory "reserved" via all currently-active
MemoryFailPoints. This has two problems:
- 1) This can account for memory twice. If a thread creates a
- MemoryFailPoint for 100 MB then allocates 99 MB, we'll see 99 MB
- less free memory and 100 MB less reserved memory. Yet, subtracting
+ 1) This can account for memory twice. If a thread creates a
+ MemoryFailPoint for 100 MB then allocates 99 MB, we'll see 99 MB
+ less free memory and 100 MB less reserved memory. Yet, subtracting
off the 100 MB is necessary because the thread may not have started
- allocating memory yet. Disposing of this class immediately after
+ allocating memory yet. Disposing of this class immediately after
front-loaded allocations have completed is a great idea.
- 2) This is still vulnerable to race conditions with other threads that don't use
+ 2) This is still vulnerable to race conditions with other threads that don't use
MemoryFailPoints.
- So this class is far from perfect. But it may be good enough to
+ So this class is far from perfect. But it may be good enough to
meaningfully reduce the frequency of OutOfMemoryExceptions in managed apps.
In Orcas or later, we might allocate some memory from the OS and add it
to a allocation context for this thread. Obviously, at that point we need
- some way of conveying when we release this block of memory. So, we
+ some way of conveying when we release this block of memory. So, we
implemented IDisposable on this type in Whidbey and expect all users to call
- this from within a using block to provide lexical scope for their memory
+ this from within a using block to provide lexical scope for their memory
usage. The call to Dispose (implicit with the using block) will give us an
- opportunity to release this memory, perhaps. We anticipate this will give
+ opportunity to release this memory, perhaps. We anticipate this will give
us the possibility of a more effective design in a future version.
In Orcas, we may also need to differentiate between allocations that would
- go into the normal managed heap vs. the large object heap, or we should
- consider checking for enough free space in both locations (with any
+ go into the normal managed heap vs. the large object heap, or we should
+ consider checking for enough free space in both locations (with any
appropriate adjustments to ensure the memory is contiguous).
*/
private static readonly ulong s_topOfMemory = GetTopOfMemory();
// Walking the address space is somewhat expensive, taking around half
- // a millisecond. Doing that per transaction limits us to a max of
- // ~2000 transactions/second. Instead, let's do this address space
+ // a millisecond. Doing that per transaction limits us to a max of
+ // ~2000 transactions/second. Instead, let's do this address space
// walk once every 10 seconds, or when we will likely fail. This
// amortization scheme can reduce the cost of a memory gate by about
// a factor of 100.
private const int MemoryCheckGranularity = 16;
// Note: This may become dynamically tunable in the future.
- // Also note that we can have different segment sizes for the normal vs.
+ // Also note that we can have different segment sizes for the normal vs.
// large object heap. We currently use the max of the two.
private static readonly ulong s_GCSegmentSize = GC.GetSegmentSize();
_reservedMemory = size;
// Check to see that we both have enough memory on the system
- // and that we have enough room within the user section of the
+ // and that we have enough room within the user section of the
// process's address space. Also, we need to use the GC segment
// size, not the amount of memory the user wants to allocate.
// Consider correcting this to reflect free memory within the GC
ulong availPageFile = 0; // available VM (physical + page file)
ulong totalAddressSpaceFree = 0; // non-contiguous free address space
- // Check for available memory, with 2 attempts at getting more
- // memory.
- // Stage 0: If we don't have enough, trigger a GC.
+ // Check for available memory, with 2 attempts at getting more
+ // memory.
+ // Stage 0: If we don't have enough, trigger a GC.
// Stage 1: If we don't have enough, try growing the swap file.
// Stage 2: Update memory state, then fail or leave loop.
//
- // (In the future, we could consider adding another stage after
+ // (In the future, we could consider adding another stage after
// Stage 0 to run finalizers. However, before doing that make sure
- // that we could abort this constructor when we call
+ // that we could abort this constructor when we call
// GC.WaitForPendingFinalizers, noting that this method uses a CER
// so it can't be aborted, and we have a critical finalizer. It
// would probably work, but do some thinking first.)
case 0:
// The GC will release empty segments to the OS. This will
// relieve us from having to guess whether there's
- // enough memory in either GC heap, and whether
- // internal fragmentation will prevent those
+ // enough memory in either GC heap, and whether
+ // internal fragmentation will prevent those
// allocations from succeeding.
GC.Collect();
continue;
continue;
case 2:
- // The call to CheckForAvailableMemory above updated our
+ // The call to CheckForAvailableMemory above updated our
// state.
if (needPageFile || needAddressSpace)
{
// Applications must call Dispose, which conceptually "releases" the
// memory that was "reserved" by the MemoryFailPoint. This affects a
// global count of reserved memory in this version (helping to throttle
- // future MemoryFailPoints) in this version. We may in the
+ // future MemoryFailPoints) in this version. We may in the
// future create an allocation context and release it in the Dispose
- // method. While the finalizer will eventually free this block of
+ // method. While the finalizer will eventually free this block of
// memory, apps will help their performance greatly by calling Dispose.
public void Dispose()
{
}
/*
- // Prototype performance
+ // Prototype performance
// Let's pretend that we returned at least some free memory to
// the GC heap. We don't know this is true - the objects could
- // have a longer lifetime, and the memory could be elsewhere in the
+ // have a longer lifetime, and the memory could be elsewhere in the
// GC heap. Additionally, we subtracted off the segment size, not
// this size. That's ok - we don't mind if this slowly degrades
// and requires us to refresh the value a little bit sooner.
-// Licensed to the .NET Foundation under one or more agreements.
+// 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.
namespace System.Runtime.Remoting
{
- public class ObjectHandle : MarshalByRefObject
+ public class ObjectHandle : MarshalByRefObject
{
private object? _wrappedObject;
{
//
// #SafeSerialization
- //
+ //
// Types which are serializable via the ISerializable interface have a problem when it comes to allowing
// transparent subtypes which can allow themselves to serialize since the GetObjectData method is
// SecurityCritical.
- //
+ //
// For instance, System.Exception implements ISerializable, however it is also desirable to have
// transparent exceptions with their own fields that need to be serialized. (For instance, in transparent
// assemblies such as the DLR and F#, or even in partial trust application code). Since overriding
// GetObjectData requires that the overriding method be security critical, this won't work directly.
//
// SafeSerializationManager solves this problem by allowing any partial trust code to contribute
- // individual chunks of serializable data to be included in the serialized version of the derived class.
+ // individual chunks of serializable data to be included in the serialized version of the derived class.
// These chunks are then deserialized back out of the serialized type and notified that they should
// populate the fields of the deserialized object when serialization is complete. This allows partial
// trust or transparent code to participate in serialization of an ISerializable type without having to
// create serializable objects which implement the ISafeSerializationData interface and add them to the
// collection of other serialized data by calling AddSerializedState on the SafeSerializationEventArgs
// passed into the event.
- //
+ //
// By using an event rather than a virtual method on the base ISerializable object, we allow multiple
// potentially untrusted subclasses to participate in serialization, without each one having to ensure
// that it calls up to the base type in order for the whole system to work. (For instance Exception :
// TrustedException : UntrustedException, in this scenario UntrustedException would be able to override
// the virtual method an prevent TrustedException from ever seeing the method call, either accidentally
// or maliciously).
- //
+ //
// Further, by only allowing additions of new chunks of serialization state rather than exposing the
// whole underlying list, we avoid exposing potentially sensitive serialized state to any of the
// potentially untrusted subclasses.
- //
+ //
// At deserialization time, SafeSerializationManager performs the reverse operation. It deserializes the
// chunks of serialized state, and then notifies them that the object they belong to is deserialized by
// calling their CompleteSerialization method. In repsonse to this call, the state objects populate the
// fields of the object being deserialized with the state that they held.
- //
+ //
// From a security perspective, the chunks of serialized state can only contain data that the specific
// subclass itself had access to read (otherwise it wouldn't be able to populate the type with that
// data), as opposed to having access to far more data in the SerializationInfo that GetObjectData uses.
// Similarly, at deserialization time, the serialized state can only modify fields that the type itself
// has access to (again, as opposed to the full SerializationInfo which could be modified).
- //
+ //
// Individual types which wish to participate in safe serialization do so by containing an instance of a
// SafeSerializationManager and exposing its serialization event. During GetObjectData, the
// SafeSerializationManager is serialized just like any other field of the containing type. However, at
// the end of serialization it is called back one last time to CompleteSerialization.
- //
+ //
// In CompleteSerialization, if the SafeSerializationManager detects that it has extra chunks of
// data to handle, it substitutes the root type being serialized (formerly the real type hosting the
// SafeSerializationManager) with itself. This allows it to gain more control over the deserialization
//
// That is, the serialized data claims to be of type SafeSerializationManager, however contains only the
// data from the real object being serialized along with one bit of safe serialization metadata.
- //
+ //
// At deserialization time, since the serialized data claims to be of type SafeSerializationManager, the
// root object being created is an instance of the SafeSerializationManager class. However, it detects
// that this isn't a real SafeSerializationManager (by looking for the real type field in the metadata),
// and simply saves away the SerializationInfo and the real type being deserialized.
- //
+ //
// Since SafeSerializationManager implements IObjectReference, the next step of deserialization is the
// GetRealObject callback. This callback is the one responsible for getting the
// SafeSerializationManager out of the way and instead creating an instance of the actual type which was
// serialized.
- //
+ //
// It does this by first creating an instance of the real type being deserialzed (saved away in the
// deserialzation constructor), but not running any of its constructors. Instead, it walks the
// inheritance hierarchy (moving toward the most derived type) looking for the last full trust type to
- // implement the standard ISerializable constructor before any type does not implement the constructor.
+ // implement the standard ISerializable constructor before any type does not implement the constructor.
// It is this last type's deserialization constructor which is then invoked, passing in the saved
// SerializationInfo. Once the constructors are run, we return this object as the real deserialized
// object.
- //
+ //
// The reason that we do this walk is so that ISerializable types can protect themselves from malicious
// input during deserialization by making their deserialization constructors unavailable to partial
// trust code. By not requiring every type have a copy of this constructor, partial trust code can
- // participate in safe serialization and not be required to have access to the parent's constructor.
- //
+ // participate in safe serialization and not be required to have access to the parent's constructor.
+ //
// It should be noted however, that this heuristic means that if a full trust type does derive from
// a transparent or partial trust type using this safe serialization mechanism, that full trust type
// will not have its constructor called. Further, the protection of not invoking partial trust
// deserialization constructors only comes into play if SafeSerializationManager is in control of
// deserialization, which means there must be at least one (even empty) safe serialization event
// handler registered.
- //
+ //
// Another interesting note is that at this point there are now two SafeSerializationManagers alive for
// this deserialization. The first object is the one which is controlling the deserialization and was
// created as the root object of the deserialization. The second one is the object which contains the
// serialized data chunks and is a data member of the real object being deserialized. For this reason,
// the data objects cannot be notified that the deserialization is complete during GetRealObject since
// the ISafeSerializationData objects are not members of the active SafeSerializationManager instance.
- //
+ //
// The next step is the OnDeserialized callback, which comes to SafeSerializableObject since it was
// pretending to be the root object of the deserialization. It responds to this callback by calling
// any existing OnDeserialized callback on the real type that was deserialized.
- //
+ //
// The real type needs to call its data member SafeSerializationData object's CompleteDeserialization
// method in response to the OnDeserialized call. This CompleteDeserialization call will then iterate
// through the ISafeSerializationData objects calling each of their CompleteDeserialization methods so
// that they can plug the nearly-complete object with their saved data.
- //
+ //
// The reason for having a new ISafeSerializationData interface which is basically identical to
// IDeserializationCallback is that IDeserializationCallback will be called on the stored data chunks
- // by the serialization code when they are deserialized, and that's not a desirable behavior.
+ // by the serialization code when they are deserialized, and that's not a desirable behavior.
// Essentially, we need to change the meaning of the object parameter to mean "parent object which
// participated in safe serialization", rather than "this object".
- //
+ //
// Implementing safe serialization on an ISerialiable type is relatively straight forward. (For an
// example, see System.Exception):
- //
+ //
// 1. Include a data member of type SafeSerializationManager:
- //
+ //
// private SafeSerializationManager _safeSerializationManager;
- //
+ //
// 2. Add a protected SerializeObjectState event, which passes through to the SafeSerializationManager:
- //
+ //
// protected event EventHandler<SafeSerializationEventArgs>? SerializeObjectState
// {
// add { _safeSerializationManager.SerializeObjectState += value; }
// }
//
// 3. Serialize the safe serialization object in GetObjectData, and call its CompleteSerialization method:
- //
+ //
// {
// info.AddValue("_safeSerializationManager", _safeSerializationManager, typeof(SafeSerializationManager));
// _safeSerializationManager.CompleteSerialization(this, info, context);
// }
//
// 4. Add an OnDeserialized handler if one doesn't already exist, and call CompleteDeserialization in it:
- //
+ //
// [OnDeserialized]
// private void OnDeserialized(StreamingContext context)
// {
// }
//
// On the client side, using safe serialization is also pretty easy. For example:
- //
+ //
// [Serializable]
// public class TransparentException : Exception
// {
// set { _state._extraData = value; }
// }
// }
- //
+ //
// Interface to be supported by objects which are stored in safe serialization stores
public interface ISafeSerializationData
public class SerializationException : SystemException
{
/// <summary>
- /// Creates a new SerializationException with its message
+ /// Creates a new SerializationException with its message
/// string set to a default message.
/// </summary>
public SerializationException()
{
private const int DefaultSize = 4;
- // Even though we have a dictionary, we're still keeping all the arrays around for back-compat.
+ // Even though we have a dictionary, we're still keeping all the arrays around for back-compat.
// Otherwise we may run into potentially breaking behaviors like GetEnumerator() not returning entries in the same order they were added.
private string[] _names;
private object?[] _values;
private string _rootTypeName;
private string _rootTypeAssemblyName;
private Type _rootType;
-
- internal static AsyncLocal<bool> AsyncDeserializationInProgress { get; } = new AsyncLocal<bool>();
+
+ internal static AsyncLocal<bool> AsyncDeserializationInProgress { get; } = new AsyncLocal<bool>();
#if !CORECLR
// On AoT, assume private members are reflection blocked, so there's no further protection required
}
}
}
-
+
return new DeserializationToken(null);
}
[CLSCompliant(false)]
- public SerializationInfo(Type type, IFormatterConverter converter)
+ public SerializationInfo(Type type, IFormatterConverter converter)
{
if ((object)type == null)
{
/// <summary>
/// Finds the value if it exists in the current data. If it does, we replace
- /// the values, if not, we append it to the end. This is useful to the
+ /// the values, if not, we append it to the end. This is useful to the
/// ObjectManager when it's performing fixups.
- ///
+ ///
/// All error checking is done with asserts. Although public in coreclr,
/// it's not exposed in a contract and is only meant to be used by corefx.
///
- /// This isn't a public API, but it gets invoked dynamically by
+ /// This isn't a public API, but it gets invoked dynamically by
/// BinaryFormatter
///
/// This should not be used by clients: exposing out this functionality would allow children
**
**
**
-** The [NonVersionable] attribute is applied to indicate that the implementation
+** The [NonVersionable] attribute is applied to indicate that the implementation
** of a particular member or layout of a struct cannot be changed for given platform in incompatible way.
-** This allows cross-module inlining of methods and data structures whose implementation
-** is never changed in ReadyToRun native images. Any changes to such members or types would be
+** This allows cross-module inlining of methods and data structures whose implementation
+** is never changed in ReadyToRun native images. Any changes to such members or types would be
** breaking changes for ReadyToRun.
**
** Applying this type also has the side effect that the inlining tables in R2R images will not
** report that inlining of NonVersionable attributed methods occured. These inlining tables are used
** by profilers to figure out the set of methods that need to be rejited when one method is instrumented,
** so in effect NonVersionable methods are also non-instrumentable. Generally this is OK for
-** extremely trivial low level methods where NonVersionable gets used, but if there is any plan to
+** extremely trivial low level methods where NonVersionable gets used, but if there is any plan to
** significantly extend its usage or allow 3rd parties to use it please discuss with the diagnostics team.
===========================================================*/
protected override bool IsValueTypeImpl()
{
// We need to return true for generic parameters with the ValueType constraint.
- // So we cannot use the faster RuntimeTypeHandle.IsValueType because it returns
+ // So we cannot use the faster RuntimeTypeHandle.IsValueType because it returns
// false for all generic parameters.
if (this == typeof(ValueType) || this == typeof(Enum))
return false;
}
return RuntimeTypeHandle.GetBaseType(this);
- }
+ }
}
-}
\ No newline at end of file
+}
// Compares this object to another object, returning an integer that
- // indicates the relationship.
+ // indicates the relationship.
// Returns a value less than zero if this object
// null is considered to be less than any instance.
// If object is not of type SByte, this method throws an ArgumentException.
- //
+ //
public int CompareTo(object? obj)
{
if (obj == null)
}
// Parses a signed byte from a String in the given style. If
- // a NumberFormatInfo isn't specified, the current culture's
+ // a NumberFormatInfo isn't specified, the current culture's
// NumberFormatInfo is assumed.
- //
+ //
[CLSCompliant(false)]
public static sbyte Parse(string s, NumberStyles style, IFormatProvider? provider)
{
//
// IConvertible implementation
- //
+ //
public TypeCode GetTypeCode()
{
NotVisibleByDefault = 1
}
}
-
namespace System.Security.Principal
{
- public enum PrincipalPolicy
+ public enum PrincipalPolicy
{
// Note: it's important that the default policy has the value 0.
UnauthenticatedPrincipal = 0,
Level2 = 2, // v4.0 transparency model
}
}
-
-// Licensed to the .NET Foundation under one or more agreements.
+// 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.
while (lo <= hi)
{
// PERF: `lo` or `hi` will never be negative inside the loop,
- // so computing median using uints is safe since we know
+ // so computing median using uints is safe since we know
// `length <= int.MaxValue`, and indices are >= 0
- // and thus cannot overflow an uint.
- // Saves one subtraction per loop compared to
+ // and thus cannot overflow an uint.
+ // Saves one subtraction per loop compared to
// `int i = lo + ((hi - lo) >> 1);`
int i = (int)(((uint)hi + (uint)lo) >> 1);
SequentialScan:
// In the non-vector case lengthToExamine is the total length.
// In the vector case lengthToExamine first aligns to Vector,
- // then in a second pass after the Vector lengths is the
+ // then in a second pass after the Vector lengths is the
// remaining data that is shorter than a Vector length.
while (lengthToExamine >= 4)
{
if (((nint)Unsafe.AsPointer(ref Unsafe.Add(ref searchSpace, (IntPtr)offset)) & (nint)(Vector256<byte>.Count - 1)) != 0)
{
// Not currently aligned to Vector256 (is aligned to Vector128); this can cause a problem for searches
- // with no upper bound e.g. String.wcslen. Start with a check on Vector128 to align to Vector256,
+ // with no upper bound e.g. String.wcslen. Start with a check on Vector128 to align to Vector256,
// before moving to processing Vector256.
- // If the input searchSpan has been fixed or pinned, this ensures we do not fault across memory pages
- // while searching for an end of string. Specifically that this assumes that the length is either correct
- // or that the data is pinned otherwise it may cause an AccessViolation from crossing a page boundary into an
+ // If the input searchSpan has been fixed or pinned, this ensures we do not fault across memory pages
+ // while searching for an end of string. Specifically that this assumes that the length is either correct
+ // or that the data is pinned otherwise it may cause an AccessViolation from crossing a page boundary into an
// unowned page. If the search is unbounded (e.g. null terminator in wcslen) and the search value is not found,
- // again this will likely cause an AccessViolation. However, correctly bounded searches will return -1 rather
+ // again this will likely cause an AccessViolation. However, correctly bounded searches will return -1 rather
// than ever causing an AV.
- // If the searchSpan has not been fixed or pinned the GC can relocate it during the execution of this
+ // If the searchSpan has not been fixed or pinned the GC can relocate it during the execution of this
// method, so the alignment only acts as best endeavour. The GC cost is likely to dominate over
- // the misalignment that may occur after; to we default to giving the GC a free hand to relocate and
+ // the misalignment that may occur after; to we default to giving the GC a free hand to relocate and
// its up to the caller whether they are operating over fixed data.
Vector128<ushort> values = Vector128.Create((ushort)value);
Vector128<ushort> search = LoadVector128(ref searchSpace, offset);
continue;
}
- // Find bitflag offset of first match and add to current offset,
+ // Find bitflag offset of first match and add to current offset,
// flags are in bytes so divide for chars
return (int)(offset + (BitOperations.TrailingZeroCount(matches) / sizeof(char)));
} while (lengthToExamine > 0);
}
else
{
- // Find bitflag offset of first match and add to current offset,
+ // Find bitflag offset of first match and add to current offset,
// flags are in bytes so divide for chars
return (int)(offset + (BitOperations.TrailingZeroCount(matches) / sizeof(char)));
}
continue;
}
- // Find bitflag offset of first match and add to current offset,
+ // Find bitflag offset of first match and add to current offset,
// flags are in bytes so divide for chars
return (int)(offset + (BitOperations.TrailingZeroCount(matches) / sizeof(char)));
} while (lengthToExamine > 0);
const int ElementsPerByte = sizeof(ushort) / sizeof(byte);
// Figure out how many characters to read sequentially until we are vector aligned
// This is equivalent to:
- // unaligned = ((int)pCh % Unsafe.SizeOf<Vector<ushort>>()) / ElementsPerByte
+ // unaligned = ((int)pCh % Unsafe.SizeOf<Vector<ushort>>()) / ElementsPerByte
// length = (Vector<ushort>.Count - unaligned) % Vector<ushort>.Count
// This alignment is only valid if the GC does not relocate; so we use ReadUnaligned to get the data.
// given range of lengths. For example, the lengths [ 4 .. 7 ] are handled by a single
// branch, [ 2 .. 3 ] are handled by a single branch, and [ 1 ] is handled by a single
// branch.
- //
+ //
// We can write both forward and backward as a perf improvement. For example,
// the lengths [ 4 .. 7 ] can be handled by zeroing out the first four natural
// words and the last 3 natural words. In the best case (length = 7), there are
if (*(int*)(a + 4) != *(int*)(b + 4)) goto DiffOffset4;
if (*(int*)(a + 6) != *(int*)(b + 6)) goto DiffOffset6;
if (*(int*)(a + 8) != *(int*)(b + 8)) goto DiffOffset8;
- length -= 10; a += 10; b += 10;
+ length -= 10; a += 10; b += 10;
}
#endif // BIT64
}
- // Provides a more flexible function for string comparison. See StringComparison
+ // Provides a more flexible function for string comparison. See StringComparison
// for meaning of different comparisonType.
public static int Compare(string? strA, string? strB, StringComparison comparisonType)
{
//
// The case-sensitive and culture-sensitive option is set by options,
// and the default culture is used.
- //
+ //
public bool EndsWith(string value)
{
return EndsWith(value, StringComparison.CurrentCulture);
{
throw new ArgumentNullException(nameof(value));
}
-
+
if ((object)this == (object)value)
{
CheckStringComparison(comparisonType);
// The character map is an array of 8 integers acting as map blocks. The 3 lsb
// in each byte in the character is used to index into this map to get the
// right block, the value of the remaining 5 msb are used as the bit position
- // inside this block.
+ // inside this block.
private static unsafe void InitializeProbabilisticMap(uint* charMap, ReadOnlySpan<char> anyOf)
{
bool hasAscii = false;
private static readonly CultureAwareComparer s_invariantCulture = new CultureAwareComparer(CultureInfo.InvariantCulture, CompareOptions.None);
private static readonly CultureAwareComparer s_invariantCultureIgnoreCase = new CultureAwareComparer(CultureInfo.InvariantCulture, CompareOptions.IgnoreCase);
private static readonly OrdinalCaseSensitiveComparer s_ordinal = new OrdinalCaseSensitiveComparer();
- private static readonly OrdinalIgnoreCaseComparer s_ordinalIgnoreCase = new OrdinalIgnoreCaseComparer();
+ private static readonly OrdinalIgnoreCaseComparer s_ordinalIgnoreCase = new OrdinalIgnoreCaseComparer();
public static StringComparer InvariantCulture
{
{
throw new ArgumentNullException(nameof(culture));
}
-
+
return new CultureAwareComparer(culture, ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
}
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public class OrdinalComparer : StringComparer
+ public class OrdinalComparer : StringComparer
{
private readonly bool _ignoreCase; // Do not rename (binary serialization)
return obj.GetHashCode();
}
- // Equals method for the comparer itself.
+ // Equals method for the comparer itself.
public override bool Equals(object? obj)
{
if (!(obj is OrdinalComparer comparer))
}
}
- // Char wasn't in our table
+ // Char wasn't in our table
return '\0';
}
}
}
-
{
bytesUnknown = bytesUnknown ?? Array.Empty<byte>();
- // Create a string representation of our bytes.
+ // Create a string representation of our bytes.
StringBuilder strBytes = new StringBuilder(bytesUnknown.Length * 3);
int i;
* are no longer responsible for handling anything related to the EncoderNLS / DecoderNLS
* infrastructure, nor are they responsible for implementing anything related to fallback
* buffers logic.
- *
+ *
* Instead, subclassed types are responsible only for transcoding of individual scalar values
* to and from the encoding's byte representation (see the two methods immediately below).
* They can optionally implement fast-path logic to perform bulk transcoding up until the
* first segment of data that cannot be transcoded. They can special-case certain fallback
* mechanisms if desired.
- *
+ *
* Most of the fast-path code is written using raw pointers as the exchange types, just as
* in the standard Encoding infrastructure. Since the fallback logic is more complex, most
* of it is written using type-safe constructs like Span<T>, with some amount of glue to
* allow it to work correctly with pointer-based fast-path code.
- *
+ *
* A typical call graph for GetBytes is represented below, using ASCIIEncoding as an example.
- *
+ *
* ASCIIEncoding.GetBytes(...) [non-EncoderNLS path, public virtual override]
* `- <parameter validation>
* - ASCIIEncoding.GetBytesCommon [private helper method per derived type, inlined]
* - <drain the fallback buffer to the destination>
* - <loop until source is fully consumed or destination is full>
* - <signal full or partial success to EncoderNLS instance / throw if necessary>
- *
+ *
* The call graph for GetBytes(..., EncoderNLS) is similar:
- *
+ *
* Encoding.GetBytes(..., EncoderNLS) [base implementation]
* `- <if no leftover data from previous invocation, invoke fast-path>
* - <if fast-path invocation above completed, return immediately>
* - <if all data transcoded, return immediately>
* - <if all data not transcoded...>
* `- Encoding.GetBytesWithFallback [virtual method as described above]
- *
+ *
* There are different considerations in each call graph for things like error handling,
* since the error conditions will be different depending on whether or not an EncoderNLS
* instance is available and what values its properties have.
this.SetDefaultFallbacks();
}
- // This constructor is needed to allow any sub-classing implementation to provide encoder/decoder fallback objects
- // because the encoding object is always created as read-only object and don't allow setting encoder/decoder fallback
- // after the creation is done.
+ // This constructor is needed to allow any sub-classing implementation to provide encoder/decoder fallback objects
+ // because the encoding object is always created as read-only object and don't allow setting encoder/decoder fallback
+ // after the creation is done.
protected Encoding(int codePage, EncoderFallback? encoderFallback, DecoderFallback? decoderFallback)
{
// Validate code page
{
GetDataItem();
}
-
+
return _dataItem!.DisplayName;
}
}
{
_encoding = encoding;
}
-
+
public object GetRealObject(StreamingContext context)
{
throw new PlatformNotSupportedException();
// Using indices from s_encodingNamesIndices, we binary search this string when mapping
// an encoding name to a codepage. Note that these names are all lowercase and are
// sorted alphabetically.
- //
+ //
private const string s_encodingNames =
"ansi_x3.4-1968" + // 20127
"ansi_x3.4-1986" + // 20127
429
};
- //
+ //
// s_codePagesByName contains the list of supported codepages which match the encoding
// names listed in s_encodingNames. The way mapping works is we binary search
// s_encodingNames using s_encodingNamesIndices until we find a match for a given name.
65001 // x-unicode-2-0-utf-8
};
- //
+ //
// When retrieving the value for System.Text.Encoding.WebName or
// System.Text.Encoding.EncodingName given System.Text.Encoding.CodePage,
// we perform a linear search on s_mappedCodePages to find the index of the
65001 // utf-8
};
- //
+ //
// s_uiFamilyCodePages is indexed by the corresponding index in s_mappedCodePages.
//
private static readonly int[] s_uiFamilyCodePages = new int[]
1200
};
- //
+ //
// s_webNames is a concatenation of the default encoding names
// for each code page. It is used in retrieving the value for
// System.Text.Encoding.WebName given System.Text.Encoding.CodePage.
"utf-7" + // 65000
"utf-8"; // 65001
- //
+ //
// s_webNameIndices contains the start index of each code page's default
// web name in the string s_webNames. It is indexed by an index into
// s_mappedCodePages.
56
};
- //
+ //
// s_englishNames is the concatenation of the English names for each codepage.
// It is used in retrieving the value for System.Text.Encoding.EncodingName
// given System.Text.Encoding.CodePage.
// This is done rather than using a large readonly array of strings to avoid
// generating a large amount of code in the static constructor.
- //
+ //
private const string s_englishNames =
"Unicode" + // 1200
"Unicode (Big-Endian)" + // 1201
"Unicode (UTF-7)" + // 65000
"Unicode (UTF-8)"; // 65001
- //
+ //
// s_englishNameIndices contains the start index of each code page's English
// name in the string s_englishNames. It is indexed by an index into
// s_mappedCodePages.
115, // Unicode (UTF-8) (65001)
130
};
-
+
// redeclaring these constants here for readability below
private const uint MIMECONTF_MAILNEWS = Encoding.MIMECONTF_MAILNEWS;
private const uint MIMECONTF_BROWSER = Encoding.MIMECONTF_BROWSER;
// Returns the number of bytes required to encode a range of characters in
// a character array.
- //
+ //
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
fixed (char* pChars = s)
return GetByteCount(pChars, s.Length, null);
- }
+ }
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
-
+
// Call it with empty encoder
return GetByteCount(chars, count, null);
}
// Alternatively, the GetMaxByteCount method can be used to
// determine the maximum number of bytes that will be produced for a given
// number of characters, regardless of the actual character values.
- //
+ //
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// Returns the number of characters produced by decoding a range of bytes
// in a byte array.
- //
+ //
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
if (index < 0 || count < 0)
throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
-
+
if (bytes.Length - index < count)
throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (count < 0)
throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
-
+
return GetCharCount(bytes, count, null);
}
if (charCount < 0 || byteCount < 0)
throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
-
+
return GetChars(bytes, byteCount, chars, charCount, null);
}
// Returns a string containing the decoded representation of a range of
// bytes in a byte array.
- //
+ //
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// Avoid problems with empty input buffer
if (count == 0) return string.Empty;
-
+
fixed (byte* pBytes = bytes)
return string.CreateStringFromEncoding(
pBytes + index, count, this);
/// GetChunks returns ChunkEnumerator that follows the IEnumerable pattern and
/// thus can be used in a C# 'foreach' statements to retreive the data in the StringBuilder
/// as chunks (ReadOnlyMemory) of characters. An example use is:
- ///
+ ///
/// foreach (ReadOnlyMemory<char> chunk in sb.GetChunks())
/// foreach(char c in chunk.Span)
/// { /* operation on c }
///
/// It is undefined what happens if the StringBuilder is modified while the chunk
/// enumeration is incomplete. StringBuilder is also not thread-safe, so operating
- /// on it with concurrent threads is illegal. Finally the ReadOnlyMemory chunks returned
- /// are NOT guarenteed to remain unchanged if the StringBuilder is modified, so do
+ /// on it with concurrent threads is illegal. Finally the ReadOnlyMemory chunks returned
+ /// are NOT guarenteed to remain unchanged if the StringBuilder is modified, so do
/// not cache them for later use either. This API's purpose is efficiently extracting
- /// the data of a CONSTANT StringBuilder.
- ///
- /// Creating a ReadOnlySpan from a ReadOnlyMemory (the .Span property) is expensive
- /// compared to the fetching of the character, so create a local variable for the SPAN
- /// if you need to use it in a nested for statement. For example
- ///
+ /// the data of a CONSTANT StringBuilder.
+ ///
+ /// Creating a ReadOnlySpan from a ReadOnlyMemory (the .Span property) is expensive
+ /// compared to the fetching of the character, so create a local variable for the SPAN
+ /// if you need to use it in a nested for statement. For example
+ ///
/// foreach (ReadOnlyMemory<char> chunk in sb.GetChunks())
/// {
/// var span = chunk.Span;
public ChunkEnumerator GetChunks() => new ChunkEnumerator(this);
/// <summary>
- /// ChunkEnumerator supports both the IEnumerable and IEnumerator pattern so foreach
- /// works (see GetChunks). It needs to be public (so the compiler can use it
+ /// ChunkEnumerator supports both the IEnumerable and IEnumerator pattern so foreach
+ /// works (see GetChunks). It needs to be public (so the compiler can use it
/// when building a foreach statement) but users typically don't use it explicitly.
- /// (which is why it is a nested type).
+ /// (which is why it is a nested type).
/// </summary>
public struct ChunkEnumerator
{
private readonly StringBuilder _firstChunk; // The first Stringbuilder chunk (which is the end of the logical string)
- private StringBuilder? _currentChunk; // The chunk that this enumerator is currently returning (Current).
+ private StringBuilder? _currentChunk; // The chunk that this enumerator is currently returning (Current).
private readonly ManyChunkInfo? _manyChunks; // Only used for long string builders with many chunks (see constructor)
/// <summary>
- /// Implement IEnumerable.GetEnumerator() to return 'this' as the IEnumerator
+ /// Implement IEnumerable.GetEnumerator() to return 'this' as the IEnumerator
/// </summary>
[ComponentModel.EditorBrowsable(ComponentModel.EditorBrowsableState.Never)] // Only here to make foreach work
public ChunkEnumerator GetEnumerator() { return this; }
{
return false;
}
-
+
if (_manyChunks != null)
{
{
Debug.Assert(stringBuilder != null);
_firstChunk = stringBuilder;
- _currentChunk = null; // MoveNext will find the last chunk if we do this.
+ _currentChunk = null; // MoveNext will find the last chunk if we do this.
_manyChunks = null;
// There is a performance-vs-allocation tradeoff. Because the chunks
// are a linked list with each chunk pointing to its PREDECESSOR, walking
// the list FORWARD is not efficient. If there are few chunks (< 8) we
- // simply scan from the start each time, and tolerate the N*N behavior.
+ // simply scan from the start each time, and tolerate the N*N behavior.
// However above this size, we allocate an array to hold pointers to all
- // the chunks and we can be efficient for large N.
+ // the chunks and we can be efficient for large N.
int chunkCount = ChunkCount(stringBuilder);
if (8 < chunkCount)
{
_manyChunks = new ManyChunkInfo(stringBuilder, chunkCount);
}
-
+
}
private static int ChunkCount(StringBuilder? stringBuilder)
}
/// <summary>
- /// Used to hold all the chunks indexes when you have many chunks.
+ /// Used to hold all the chunks indexes when you have many chunks.
/// </summary>
private class ManyChunkInfo
{
- private readonly StringBuilder[] _chunks; // These are in normal order (first chunk first)
+ private readonly StringBuilder[] _chunks; // These are in normal order (first chunk first)
private int _chunkPos;
public bool MoveNext(ref StringBuilder? current)
pos++;
string? s = null;
string? itemFormat = null;
-
+
if (cf != null)
{
if (itemFormatSpan.Length != 0)
{
Append(' ', pad);
}
-
+
Append(s);
if (leftJustify && pad > 0)
{
{
return false;
}
-
+
Debug.Assert(thisChunk != null && sbChunk != null);
if (thisChunk.m_ChunkChars[thisChunkIndex] != sbChunk.m_ChunkChars[sbChunkIndex])
{
{
MakeRoom(targetChunk.m_ChunkOffset + targetIndexInChunk, delta, out targetChunk, out targetIndexInChunk, true);
}
-
+
// We made certain that characters after the insertion point are not moved,
int i = 0;
for (;;)
{
throw new OutOfMemoryException();
}
-
+
// Allocate the array before updating any state to avoid leaving inconsistent state behind in case of out of memory exception
char[] chunkChars = new char[newBlockLength];
private const int DefaultCapacity = 16; // == StringBuilder.DefaultCapacity
// WARNING: We allow diagnostic tools to directly inspect this member (t_cachedInstance).
- // See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
- // Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
+ // See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
+ // Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
// Get in touch with the diagnostics team if you have questions.
[ThreadStatic]
private static StringBuilder? t_cachedInstance;
Debug.Assert(bytes >= byteStart + 4 || chars == charStart,
"[UTF32Encoding.GetChars]Expected to have consumed bytes or throw (normal char)");
bytes -= 4; // get back to where we were
- iChar = 0; // Remembering nothing
+ iChar = 0; // Remembering nothing
ThrowCharsOverflow(decoder, chars == charStart);// Might throw, if no chars output
break; // Stop here, didn't throw
}
GetType() != typeof(UTF32Encoding) ? new ReadOnlySpan<byte>(GetPreamble()) : // in case a derived UTF32Encoding overrode GetPreamble
!_emitUTF32ByteOrderMark ? default :
_bigEndian ? (ReadOnlySpan<byte>)new byte[4] { 0x00, 0x00, 0xFE, 0xFF } : // uses C# compiler's optimization for static byte[] data
- (ReadOnlySpan<byte>)new byte[4] { 0xFF, 0xFE, 0x00, 0x00 };
+ (ReadOnlySpan<byte>)new byte[4] { 0xFF, 0xFE, 0x00, 0x00 };
public override bool Equals(object? value)
{
// If we got here, it means we saw some non-ASCII data, so within our
// vectorized code paths below we'll handle all non-surrogate UTF-16
// code points branchlessly. We'll only branch if we see surrogates.
- //
+ //
// We still optimistically assume the data is mostly ASCII. This means that the
// number of UTF-8 code units and the number of scalars almost matches the number
// of UTF-16 code units. As we go through the input and find non-ASCII
// or palignr available to us, we'll do this as a loop. We won't look at
// the very last high surrogate char element since we don't yet know if
// the next vector read will have a low surrogate char element.
-
+
if (lowSurrogateChars[0] != 0)
{
goto Error; // error: start of buffer contains standalone low surrogate char
while (longChars < longEnd)
{
// See if we potentially have surrogates (0x8000 bit set)
- // (We're either big endian on a big endian machine or little endian on
- // a little endian machine so that'll work)
+ // (We're either big endian on a big endian machine or little endian on
+ // a little endian machine so that'll work)
if ((0x8000800080008000 & *longChars) != 0)
{
// See if any of these are high or low surrogates (0xd800 - 0xdfff). If the high
}
// else none are surrogates, so we can use them.
}
- // else all < 0x8000 so we can use them
+ // else all < 0x8000 so we can use them
// We already counted these four chars, go to next long.
longChars++;
// No fallback, maybe we can do it fast
#if FASTLOOP
// If endianess is backwards then each pair of bytes would be backwards.
- if ( (bigEndian ^ BitConverter.IsLittleEndian) &&
+ if ( (bigEndian ^ BitConverter.IsLittleEndian) &&
#if BIT64
(unchecked((long)chars) & 7) == 0 &&
#else
while (longChars < longEnd)
{
// See if we potentially have surrogates (0x8000 bit set)
- // (We're either big endian on a big endian machine or little endian on
- // a little endian machine so that'll work)
+ // (We're either big endian on a big endian machine or little endian on
+ // a little endian machine so that'll work)
if ((0x8000800080008000 & *longChars) != 0)
{
// See if any of these are high or low surrogates (0xd800 - 0xdfff). If the high
{
// These must have both been from the fallbacks.
// Both of these MUST have been from a fallback because if the 1st wasn't
- // from a fallback, then a high surrogate followed by an illegal char
+ // from a fallback, then a high surrogate followed by an illegal char
// would've caused the high surrogate to fall back. If a high surrogate
// fell back, then it was consumed and both chars came from the fallback.
fallbackBuffer.MovePrevious(); // Didn't use either fallback surrogate
while (longBytes < longEnd)
{
// See if we potentially have surrogates (0x8000 bit set)
- // (We're either big endian on a big endian machine or little endian on
+ // (We're either big endian on a big endian machine or little endian on
// a little endian machine so that'll work)
if ((0x8000800080008000 & *longBytes) != 0)
{
while (longBytes < longEnd)
{
// See if we potentially have surrogates (0x8000 bit set)
- // (We're either big endian on a big endian machine or little endian on
+ // (We're either big endian on a big endian machine or little endian on
// a little endian machine so that'll work)
if ((0x8000800080008000 & *longBytes) != 0)
{
{
// base calls reset
}
-
+
public override void Reset()
{
lastByte = -1;
}
}
}
-
public static bool IsValidUnicodeScalar(uint value)
{
// This is an optimized check that on x86 is just three instructions: lea, xor, cmp.
- //
+ //
// After the subtraction operation, the input value is modified as such:
// [ 00000000..0010FFFF ] -> [ FFEF0000..FFFFFFFF ]
//
**
**
**
-** Purpose: Custom attribute to indicate that the field should be treated
+** Purpose: Custom attribute to indicate that the field should be treated
** as a static relative to a thread.
-**
+**
**
**
===========================================================*/
public AutoResetEvent(bool initialState) : base(initialState, EventResetMode.AutoReset) { }
}
}
-
/// <remarks>
/// <para>
/// A <see cref="CancellationToken"/> may be created directly in an unchangeable canceled or non-canceled state
- /// using the CancellationToken's constructors. However, to have a CancellationToken that can change
- /// from a non-canceled to a canceled state,
+ /// using the CancellationToken's constructors. However, to have a CancellationToken that can change
+ /// from a non-canceled to a canceled state,
/// <see cref="System.Threading.CancellationTokenSource">CancellationTokenSource</see> must be used.
- /// CancellationTokenSource exposes the associated CancellationToken that may be canceled by the source through its
- /// <see cref="System.Threading.CancellationTokenSource.Token">Token</see> property.
+ /// CancellationTokenSource exposes the associated CancellationToken that may be canceled by the source through its
+ /// <see cref="System.Threading.CancellationTokenSource.Token">Token</see> property.
/// </para>
/// <para>
- /// Once canceled, a token may not transition to a non-canceled state, and a token whose
+ /// Once canceled, a token may not transition to a non-canceled state, and a token whose
/// <see cref="CanBeCanceled"/> is false will never change to one that can be canceled.
/// </para>
/// <para>
[DebuggerDisplay("IsCancellationRequested = {IsCancellationRequested}")]
public readonly struct CancellationToken
{
- // The backing TokenSource.
+ // The backing TokenSource.
// if null, it implicitly represents the same thing as new CancellationToken(false).
// When required, it will be instantiated to reflect this.
private readonly CancellationTokenSource? _source;
/// <value>Whether cancellation has been requested for this token.</value>
/// <remarks>
/// <para>
- /// This property indicates whether cancellation has been requested for this token,
+ /// This property indicates whether cancellation has been requested for this token,
/// either through the token initially being constructed in a canceled state, or through
- /// calling <see cref="System.Threading.CancellationTokenSource.Cancel()">Cancel</see>
+ /// calling <see cref="System.Threading.CancellationTokenSource.Cancel()">Cancel</see>
/// on the token's associated <see cref="CancellationTokenSource"/>.
/// </para>
/// <para>
- /// If this property is true, it only guarantees that cancellation has been requested.
+ /// If this property is true, it only guarantees that cancellation has been requested.
/// It does not guarantee that every registered handler
/// has finished executing, nor that cancellation requests have finished propagating
/// to all registered handlers. Additional synchronization may be required,
/// by the <paramref name="canceled"/> parameter. If <paramref name="canceled"/> is false,
/// both <see cref="CanBeCanceled"/> and <see cref="IsCancellationRequested"/> will be false.
/// If <paramref name="canceled"/> is true,
- /// both <see cref="CanBeCanceled"/> and <see cref="IsCancellationRequested"/> will be true.
+ /// both <see cref="CanBeCanceled"/> and <see cref="IsCancellationRequested"/> will be true.
/// </remarks>
public CancellationToken(bool canceled) : this(canceled ? CancellationTokenSource.s_canceledSource : null)
{
/// </para>
/// </remarks>
/// <param name="callback">The delegate to be executed when the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.</param>
- /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
+ /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
/// be used to unregister the callback.</returns>
/// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
public CancellationTokenRegistration Register(Action callback) =>
useExecutionContext: true);
/// <summary>
- /// Registers a delegate that will be called when this
+ /// Registers a delegate that will be called when this
/// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.
/// </summary>
/// <remarks>
/// <param name="useSynchronizationContext">A Boolean value that indicates whether to capture
/// the current <see cref="T:System.Threading.SynchronizationContext">SynchronizationContext</see> and use it
/// when invoking the <paramref name="callback"/>.</param>
- /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
+ /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
/// be used to unregister the callback.</returns>
/// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
public CancellationTokenRegistration Register(Action callback, bool useSynchronizationContext) =>
useExecutionContext: true);
/// <summary>
- /// Registers a delegate that will be called when this
+ /// Registers a delegate that will be called when this
/// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="callback">The delegate to be executed when the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.</param>
/// <param name="state">The state to pass to the <paramref name="callback"/> when the delegate is invoked. This may be null.</param>
- /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
+ /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
/// be used to unregister the callback.</returns>
/// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
public CancellationTokenRegistration Register(Action<object?> callback, object? state) =>
Register(callback, state, useSynchronizationContext: false, useExecutionContext: true);
/// <summary>
- /// Registers a delegate that will be called when this
+ /// Registers a delegate that will be called when this
/// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.
/// </summary>
/// <remarks>
/// propagated out of this method call.
/// </para>
/// <para>
- /// The current <see cref="System.Threading.ExecutionContext">ExecutionContext</see>, if one exists,
+ /// The current <see cref="System.Threading.ExecutionContext">ExecutionContext</see>, if one exists,
/// will be captured along with the delegate and will be used when executing it.
/// </para>
/// </remarks>
/// <param name="useSynchronizationContext">A Boolean value that indicates whether to capture
/// the current <see cref="T:System.Threading.SynchronizationContext">SynchronizationContext</see> and use it
/// when invoking the <paramref name="callback"/>.</param>
- /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
+ /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
/// be used to unregister the callback.</returns>
/// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
/// <exception cref="T:System.ObjectDisposedException">The associated <see
Register(callback, state, useSynchronizationContext, useExecutionContext: true);
/// <summary>
- /// Registers a delegate that will be called when this
+ /// Registers a delegate that will be called when this
/// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="callback">The delegate to be executed when the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.</param>
/// <param name="state">The state to pass to the <paramref name="callback"/> when the delegate is invoked. This may be null.</param>
- /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
+ /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
/// be used to unregister the callback.</returns>
/// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
public CancellationTokenRegistration UnsafeRegister(Action<object?> callback, object? state) =>
Register(callback, state, useSynchronizationContext: false, useExecutionContext: false);
/// <summary>
- /// Registers a delegate that will be called when this
+ /// Registers a delegate that will be called when this
/// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.
/// </summary>
/// <remarks>
/// <param name="useSynchronizationContext">A Boolean value that indicates whether to capture
/// the current <see cref="T:System.Threading.SynchronizationContext">SynchronizationContext</see> and use it
/// when invoking the <paramref name="callback"/>.</param>
- /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
+ /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
/// be used to unregister the callback.</returns>
/// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
/// <exception cref="T:System.ObjectDisposedException">The associated <see
}
/// <summary>
- /// Determines whether the current <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instance is equal to the
+ /// Determines whether the current <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instance is equal to the
/// specified token.
/// </summary>
/// <param name="other">The other <see cref="T:System.Threading.CancellationToken">CancellationToken</see> to which to compare this
/// instance.</param>
/// <returns>True if the instances are equal; otherwise, false. Two tokens are equal if they are associated
- /// with the same <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> or if they were both constructed
+ /// with the same <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> or if they were both constructed
/// from public CancellationToken constructors and their <see cref="IsCancellationRequested"/> values are equal.</returns>
public bool Equals(CancellationToken other) => _source == other._source;
/// <summary>
- /// Determines whether the current <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instance is equal to the
+ /// Determines whether the current <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instance is equal to the
/// specified <see cref="T:System.Object"/>.
/// </summary>
/// <param name="other">The other object to which to compare this instance.</param>
/// <returns>True if <paramref name="other"/> is a <see cref="T:System.Threading.CancellationToken">CancellationToken</see>
/// and if the two instances are equal; otherwise, false. Two tokens are equal if they are associated
- /// with the same <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> or if they were both constructed
+ /// with the same <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> or if they were both constructed
/// from public CancellationToken constructors and their <see cref="IsCancellationRequested"/> values are equal.</returns>
/// <exception cref="T:System.ObjectDisposedException">An associated <see
/// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
/// <remarks>
/// This method provides functionality equivalent to:
/// <code>
- /// if (token.IsCancellationRequested)
+ /// if (token.IsCancellationRequested)
/// throw new OperationCanceledException(token);
/// </code>
/// </remarks>
}
/// <summary>
- /// Disposes of the registration and unregisters the target callback from the associated
+ /// Disposes of the registration and unregisters the target callback from the associated
/// <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
/// If the target callback is currently executing, this method will wait until it completes, except
/// in the degenerate cases where a callback method unregisters itself.
}
/// <summary>
- /// Disposes of the registration and unregisters the target callback from the associated
+ /// Disposes of the registration and unregisters the target callback from the associated
/// <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
/// The returned <see cref="ValueTask"/> will complete once the associated callback
/// is unregistered without having executed or once it's finished executing, except
}
/// <summary>
- /// Disposes of the registration and unregisters the target callback from the associated
+ /// Disposes of the registration and unregisters the target callback from the associated
/// <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
/// </summary>
public bool Unregister()
public static bool operator !=(CancellationTokenRegistration left, CancellationTokenRegistration right) => !left.Equals(right);
/// <summary>
- /// Determines whether the current <see cref="T:System.Threading.CancellationTokenRegistration">CancellationTokenRegistration</see> instance is equal to the
+ /// Determines whether the current <see cref="T:System.Threading.CancellationTokenRegistration">CancellationTokenRegistration</see> instance is equal to the
/// specified <see cref="T:System.Object"/>.
- /// </summary>
+ /// </summary>
/// <param name="obj">The other object to which to compare this instance.</param>
/// <returns>True, if both this and <paramref name="obj"/> are equal. False, otherwise.
/// Two <see cref="T:System.Threading.CancellationTokenRegistration">CancellationTokenRegistration</see> instances are equal if
- /// they both refer to the output of a single call to the same Register method of a
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
+ /// they both refer to the output of a single call to the same Register method of a
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
/// </returns>
public override bool Equals(object? obj) => obj is CancellationTokenRegistration && Equals((CancellationTokenRegistration)obj);
/// <summary>
- /// Determines whether the current <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instance is equal to the
+ /// Determines whether the current <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instance is equal to the
/// specified <see cref="T:System.Object"/>.
- /// </summary>
+ /// </summary>
/// <param name="other">The other <see cref="T:System.Threading.CancellationTokenRegistration">CancellationTokenRegistration</see> to which to compare this instance.</param>
/// <returns>True, if both this and <paramref name="other"/> are equal. False, otherwise.
/// Two <see cref="T:System.Threading.CancellationTokenRegistration">CancellationTokenRegistration</see> instances are equal if
- /// they both refer to the output of a single call to the same Register method of a
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
+ /// they both refer to the output of a single call to the same Register method of a
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
/// </returns>
public bool Equals(CancellationTokenRegistration other) => _node == other._node && _id == other._id;
/// </exception>
/// <remarks>
/// <para>
- /// The countdown for the delay starts during the call to the constructor. When the delay expires,
+ /// The countdown for the delay starts during the call to the constructor. When the delay expires,
/// the constructed <see cref="CancellationTokenSource"/> is canceled, if it has
/// not been canceled already.
/// </para>
/// <para>
- /// Subsequent calls to CancelAfter will reset the delay for the constructed
+ /// Subsequent calls to CancelAfter will reset the delay for the constructed
/// <see cref="CancellationTokenSource"/>, if it has not been
/// canceled already.
/// </para>
/// </exception>
/// <remarks>
/// <para>
- /// The countdown for the millisecondsDelay starts during the call to the constructor. When the millisecondsDelay expires,
+ /// The countdown for the millisecondsDelay starts during the call to the constructor. When the millisecondsDelay expires,
/// the constructed <see cref="CancellationTokenSource"/> is canceled (if it has
/// not been canceled already).
/// </para>
/// <para>
- /// Subsequent calls to CancelAfter will reset the millisecondsDelay for the constructed
+ /// Subsequent calls to CancelAfter will reset the millisecondsDelay for the constructed
/// <see cref="CancellationTokenSource"/>, if it has not been
/// canceled already.
/// </para>
/// <remarks>
/// <para>
/// The associated <see cref="CancellationToken" /> will be notified of the cancellation
- /// and will transition to a state where <see cref="CancellationToken.IsCancellationRequested"/> returns true.
+ /// and will transition to a state where <see cref="CancellationToken.IsCancellationRequested"/> returns true.
/// Any callbacks or cancelable operations registered with the <see cref="CancellationToken"/> will be executed.
/// </para>
/// <para>
/// </remarks>
/// <exception cref="AggregateException">An aggregate exception containing all the exceptions thrown
/// by the registered callbacks on the associated <see cref="CancellationToken"/>.</exception>
- /// <exception cref="ObjectDisposedException">This <see cref="CancellationTokenSource"/> has been disposed.</exception>
+ /// <exception cref="ObjectDisposedException">This <see cref="CancellationTokenSource"/> has been disposed.</exception>
public void Cancel() => Cancel(false);
/// <summary>Communicates a request for cancellation.</summary>
/// <remarks>
/// <para>
- /// The associated <see cref="CancellationToken" /> will be notified of the cancellation and will transition to a state where
+ /// The associated <see cref="CancellationToken" /> will be notified of the cancellation and will transition to a state where
/// <see cref="CancellationToken.IsCancellationRequested"/> returns true. Any callbacks or cancelable operationsregistered
/// with the <see cref="CancellationToken"/> will be executed.
/// </para>
/// <para>
- /// Cancelable operations and callbacks registered with the token should not throw exceptions.
+ /// Cancelable operations and callbacks registered with the token should not throw exceptions.
/// If <paramref name="throwOnFirstException"/> is true, an exception will immediately propagate out of the
/// call to Cancel, preventing the remaining callbacks and cancelable operations from being processed.
- /// If <paramref name="throwOnFirstException"/> is false, this overload will aggregate any
+ /// If <paramref name="throwOnFirstException"/> is false, this overload will aggregate any
/// exceptions thrown into a <see cref="AggregateException"/>,
/// such that one callback throwing an exception will not prevent other registered callbacks from being executed.
/// </para>
/// <param name="throwOnFirstException">Specifies whether exceptions should immediately propagate.</param>
/// <exception cref="AggregateException">An aggregate exception containing all the exceptions thrown
/// by the registered callbacks on the associated <see cref="CancellationToken"/>.</exception>
- /// <exception cref="ObjectDisposedException">This <see cref="CancellationTokenSource"/> has been disposed.</exception>
+ /// <exception cref="ObjectDisposedException">This <see cref="CancellationTokenSource"/> has been disposed.</exception>
public void Cancel(bool throwOnFirstException)
{
ThrowIfDisposed();
/// cref="CancellationTokenSource"/> has been disposed.
/// </exception>
/// <exception cref="ArgumentOutOfRangeException">
- /// The exception thrown when <paramref name="delay"/> is less than -1 or
+ /// The exception thrown when <paramref name="delay"/> is less than -1 or
/// greater than int.MaxValue.
/// </exception>
/// <remarks>
/// <para>
- /// The countdown for the delay starts during this call. When the delay expires,
+ /// The countdown for the delay starts during this call. When the delay expires,
/// this <see cref="CancellationTokenSource"/> is canceled, if it has
/// not been canceled already.
/// </para>
/// <para>
- /// Subsequent calls to CancelAfter will reset the delay for this
+ /// Subsequent calls to CancelAfter will reset the delay for this
/// <see cref="CancellationTokenSource"/>, if it has not been canceled already.
/// </para>
/// </remarks>
/// </exception>
/// <remarks>
/// <para>
- /// The countdown for the millisecondsDelay starts during this call. When the millisecondsDelay expires,
+ /// The countdown for the millisecondsDelay starts during this call. When the millisecondsDelay expires,
/// this <see cref="CancellationTokenSource"/> is canceled, if it has
/// not been canceled already.
/// </para>
/// <para>
- /// Subsequent calls to CancelAfter will reset the millisecondsDelay for this
+ /// Subsequent calls to CancelAfter will reset the millisecondsDelay for this
/// <see cref="CancellationTokenSource"/>, if it has not been
/// canceled already.
/// </para>
}
// There is a race condition here as a Cancel could occur between the check of
- // IsCancellationRequested and the creation of the timer. This is benign; in the
+ // IsCancellationRequested and the creation of the timer. This is benign; in the
// worst case, a timer will be created that has no effect when it expires.
// Also, if Dispose() is called right here (after ThrowIfDisposed(), before timer
// after the CTS has been disposed and/or concurrently with cts.Dispose().
// This is safe without locks because Dispose doesn't interact with values
// in the callback partitions, only nulling out the ref to existing partitions.
- //
+ //
// We also tolerate that a callback can be registered after the CTS has been
// disposed. This is safe because InternalRegister is tolerant
// of _callbackPartitions becoming null during its execution. However,
// - late enlisters to the Canceled event will have their callbacks called immediately in the Register() methods.
// - Callbacks are not called inside a lock.
- // - After transition, no more delegates will be added to the
+ // - After transition, no more delegates will be added to the
// - list of handlers, and hence it can be consumed and cleared at leisure by ExecuteCallbackHandlers.
ExecuteCallbackHandlers(throwOnFirstException);
Debug.Assert(IsCancellationCompleted, "Expected cancellation to have finished");
/// </summary>
/// <param name="token1">The first <see cref="CancellationToken">CancellationToken</see> to observe.</param>
/// <param name="token2">The second <see cref="CancellationToken">CancellationToken</see> to observe.</param>
- /// <returns>A <see cref="CancellationTokenSource"/> that is linked
+ /// <returns>A <see cref="CancellationTokenSource"/> that is linked
/// to the source tokens.</returns>
public static CancellationTokenSource CreateLinkedTokenSource(CancellationToken token1, CancellationToken token2) =>
!token1.CanBeCanceled ? CreateLinkedTokenSource(token2) :
public object? CallbackState;
public ExecutionContext? ExecutionContext;
public SynchronizationContext? SynchronizationContext;
-
+
public CallbackNode(CallbackPartition partition)
{
Debug.Assert(partition != null, "Expected non-null partition");
/// If the refcount reaches zero before the object is disposed, this method will be called with
/// <paramref name="disposed"/> set to false. If the object is then disposed, this method will be
/// called again, with <paramref name="disposed"/> set to true. If the refcount reaches zero
- /// after the object has already been disposed, this will be called a single time, with
+ /// after the object has already been disposed, this will be called a single time, with
/// <paramref name="disposed"/> set to true.
/// </remarks>
void OnFinalRelease(bool disposed);
throw Win32Marshal.GetExceptionForLastWin32Error();
return res;
}
-
+
public bool Set()
{
bool res = Interop.Kernel32.SetEvent(SafeWaitHandle);
currentThread._synchronizationContext = null;
if (currentExecutionCtx != null)
{
- // The EC always needs to be reset for this overload, as it will flow back to the caller if it performs
+ // The EC always needs to be reset for this overload, as it will flow back to the caller if it performs
// extra work prior to returning to the Dispatch loop. For example for Task-likes it will flow out of await points
RestoreChangedContextToThread(currentThread, contextToRestore: null, currentExecutionCtx);
}
internal static void RunForThreadPoolUnsafe<TState>(ExecutionContext executionContext, Action<TState> callback, in TState state)
{
- // We aren't running in try/catch as if an exception is directly thrown on the ThreadPool either process
- // will crash or its a ThreadAbortException.
+ // We aren't running in try/catch as if an exception is directly thrown on the ThreadPool either process
+ // will crash or its a ThreadAbortException.
CheckThreadPoolAndContextsAreDefault();
Debug.Assert(executionContext != null && !executionContext.m_isDefault, "ExecutionContext argument is Default.");
{
Debug.Assert(previousExecutionCtx != nextExecutionCtx);
- // Collect Change Notifications
+ // Collect Change Notifications
IAsyncLocal[]? previousChangeNotifications = previousExecutionCtx?.m_localChangeNotifications;
IAsyncLocal[]? nextChangeNotifications = nextExecutionCtx?.m_localChangeNotifications;
// Check for additional notifications in nextExecutionCtx
foreach (IAsyncLocal local in nextChangeNotifications)
{
- // If the local has a value in the previous context, we already fired the event
+ // If the local has a value in the previous context, we already fired the event
// for that local in the code above.
if (!previousExecutionCtx.m_localValues.TryGetValue(local, out object? previousValue))
{
}
}
- Thread.CurrentThread._executionContext =
+ Thread.CurrentThread._executionContext =
(!isFlowSuppressed && AsyncLocalValueMap.IsEmpty(newValues)) ?
null : // No values, return to Default context
new ExecutionContext(newValues, newChangeNotifications, isFlowSuppressed);
/// types, see other overloads of EnsureInitialized.
/// </para>
/// <para>
- /// This method may be used concurrently by multiple threads to initialize <paramref name="target"/>.
+ /// This method may be used concurrently by multiple threads to initialize <paramref name="target"/>.
/// In the event that multiple threads access this method concurrently, multiple instances of <typeparamref name="T"/>
/// may be created, but only one will be stored into <paramref name="target"/>. In such an occurrence, this method will not dispose of the
- /// objects that were not stored. If such objects must be disposed, it is up to the caller to determine
+ /// objects that were not stored. If such objects must be disposed, it is up to the caller to determine
/// if an object was not used and to then dispose of the object appropriately.
/// </para>
/// </remarks>
/// to allow null reference types, see other overloads of EnsureInitialized.
/// </para>
/// <para>
- /// This method may be used concurrently by multiple threads to initialize <paramref name="target"/>.
+ /// This method may be used concurrently by multiple threads to initialize <paramref name="target"/>.
/// In the event that multiple threads access this method concurrently, multiple instances of <typeparamref name="T"/>
/// may be created, but only one will be stored into <paramref name="target"/>. In such an occurrence, this method will not dispose of the
- /// objects that were not stored. If such objects must be disposed, it is up to the caller to determine
+ /// objects that were not stored. If such objects must be disposed, it is up to the caller to determine
/// if an object was not used and to then dispose of the object appropriately.
/// </para>
/// </remarks>
/// <typeparam name="T">The type of target.</typeparam>
/// <param name="target">A reference to the target to be initialized.</param>
/// <param name="initialized">A reference to a location tracking whether the target has been initialized.</param>
- /// <param name="syncLock">A reference to a location containing a mutual exclusive lock. If <paramref name="syncLock"/> is null,
+ /// <param name="syncLock">A reference to a location containing a mutual exclusive lock. If <paramref name="syncLock"/> is null,
/// a new object will be instantiated.
/// </param>
/// <returns>The initialized object.</returns>
/// <typeparam name="T">The type of target.</typeparam>
/// <param name="target">A reference to the target to be initialized.</param>
/// <param name="initialized">A reference to a location tracking whether the target has been initialized.</param>
- /// <param name="syncLock">A reference to a location containing a mutual exclusive lock. If <paramref name="syncLock"/> is null,
+ /// <param name="syncLock">A reference to a location containing a mutual exclusive lock. If <paramref name="syncLock"/> is null,
/// a new object will be instantiated.</param>
/// <param name="valueFactory">
/// The <see cref="T:System.Func{T}"/> to invoke in order to produce the lazily-initialized value.
/// </summary>
/// <typeparam name="T">The type of target. Has to be reference type.</typeparam>
/// <param name="target">A reference to the target to be initialized.</param>
- /// <param name="syncLock">A reference to a location containing a mutual exclusive lock. If <paramref name="syncLock"/> is null,
+ /// <param name="syncLock">A reference to a location containing a mutual exclusive lock. If <paramref name="syncLock"/> is null,
/// a new object will be instantiated.</param>
/// <param name="valueFactory">
/// The <see cref="T:System.Func{T}"/> to invoke in order to produce the lazily-initialized value.
{
/// <summary>
/// This mode makes no guarantees around the thread-safety of the <see cref="T:System.Threading.Lazy{T}"/> instance. If used from multiple threads, the behavior of the <see cref="T:System.Threading.Lazy{T}"/> is undefined.
- /// This mode should be used when a <see cref="T:System.Threading.Lazy{T}"/> is guaranteed to never be initialized from more than one thread simultaneously and high performance is crucial.
+ /// This mode should be used when a <see cref="T:System.Threading.Lazy{T}"/> is guaranteed to never be initialized from more than one thread simultaneously and high performance is crucial.
/// If valueFactory throws an exception when the <see cref="T:System.Threading.Lazy{T}"/> is initialized, the exception will be cached and returned on subsequent accesses to Value. Also, if valueFactory recursively
/// accesses Value on this <see cref="T:System.Threading.Lazy{T}"/> instance, a <see cref="T:System.InvalidOperationException"/> will be thrown.
/// </summary>
public ManualResetEvent(bool initialState) : base(initialState, EventResetMode.ManualReset) { }
}
}
-
// -- State -- //
//For a packed word a uint would seem better, but Interlocked.* doesn't support them as uint isn't CLS-compliant.
- private volatile int m_combinedState; //ie a uint. Used for the state items listed below.
+ private volatile int m_combinedState; //ie a uint. Used for the state items listed below.
//1-bit for signalled state
private const int SignalledState_BitMask = unchecked((int)0x80000000);//1000 0000 0000 0000 0000 0000 0000 0000
/// cref="ManualResetEventSlim"/>.</value>
/// <remarks>
/// Accessing this property forces initialization of an underlying event object if one hasn't
- /// already been created. To simply wait on this <see cref="ManualResetEventSlim"/>,
+ /// already been created. To simply wait on this <see cref="ManualResetEventSlim"/>,
/// the public Wait methods should be preferred.
/// </remarks>
public WaitHandle WaitHandle
private void Set(bool duringCancellation)
{
// We need to ensure that IsSet=true does not get reordered past the read of m_eventObj
- // This would be a legal movement according to the .NET memory model.
+ // This would be a legal movement according to the .NET memory model.
// The code is safe as IsSet involves an Interlocked.CompareExchange which provides a full memory barrier.
IsSet = true;
return false;
}
- // There is a race condition that Set will fail to see that there are waiters as Set does not take the lock,
+ // There is a race condition that Set will fail to see that there are waiters as Set does not take the lock,
// so after updating waiters, we must check IsSet again.
// Also, we must ensure there cannot be any reordering of the assignment to Waiters and the
// read from IsSet. This is guaranteed as Waiters{set;} involves an Interlocked.CompareExchange
}
/// <summary>
- /// When overridden in a derived class, releases the unmanaged resources used by the
+ /// When overridden in a derived class, releases the unmanaged resources used by the
/// <see cref="ManualResetEventSlim"/>, and optionally releases the managed resources.
/// </summary>
/// <param name="disposing">true to release both managed and unmanaged resources;
/// <summary>
/// Private helper method - performs Mask and shift, particular helpful to extract a field from a packed word.
- /// eg ExtractStatePortionAndShiftRight(0x12345678, 0xFF000000, 24) => 0x12, ie extracting the top 8-bits as a simple integer
- ///
+ /// eg ExtractStatePortionAndShiftRight(0x12345678, 0xFF000000, 24) => 0x12, ie extracting the top 8-bits as a simple integer
+ ///
/// ?? is there a common place to put this rather than being private to MRES?
/// </summary>
/// <param name="state"></param>
/// This is acceptable for boolean values for which the shift is unnecessary
/// eg (val & Mask) != 0 is an appropriate way to extract a boolean rather than using
/// ((val & Mask) >> shiftAmount) == 1
- ///
+ ///
/// ?? is there a common place to put this rather than being private to MRES?
/// </summary>
/// <param name="state"></param>
// These are reused wherever possible, so that a given thread will only
// allocate N of these, where N is the maximum number of locks held simultaneously
// by that thread.
- //
+ //
internal class ReaderWriterCount
{
// Which lock does this object belong to? This is a numeric ID for two reasons:
public int readercount;
// Ditto for writer/upgrader counts. These are only used if the lock allows recursion.
- // But we have to have the fields on every ReaderWriterCount instance, because
+ // But we have to have the fields on every ReaderWriterCount instance, because
// we reuse it for different locks.
public int writercount;
public int upgradecount;
/// <summary>
/// A reader-writer lock implementation that is intended to be simple, yet very
- /// efficient. In particular only 1 interlocked operation is taken for any lock
+ /// efficient. In particular only 1 interlocked operation is taken for any lock
/// operation (we use spin locks to achieve this). The spin lock is never held
/// for more than a few instructions (in particular, we never call event APIs
- /// or in fact any non-trivial API while holding the spin lock).
+ /// or in fact any non-trivial API while holding the spin lock).
/// </summary>
public class ReaderWriterLockSlim : IDisposable
{
private readonly bool _fIsReentrant;
// Lock specification for _spinLock: This lock protects exactly the local fields associated with this
- // instance of ReaderWriterLockSlim. It does NOT protect the memory associated with
+ // instance of ReaderWriterLockSlim. It does NOT protect the memory associated with
// the events that hang off this lock (eg writeEvent, readEvent upgradeEvent).
SpinLock _spinLock;
- // These variables allow use to avoid Setting events (which is expensive) if we don't have to.
- private uint _numWriteWaiters; // maximum number of threads that can be doing a WaitOne on the writeEvent
+ // These variables allow use to avoid Setting events (which is expensive) if we don't have to.
+ private uint _numWriteWaiters; // maximum number of threads that can be doing a WaitOne on the writeEvent
private uint _numReadWaiters; // maximum number of threads that can be doing a WaitOne on the readEvent
- private uint _numWriteUpgradeWaiters; // maximum number of threads that can be doing a WaitOne on the upgradeEvent (at most 1).
+ private uint _numWriteUpgradeWaiters; // maximum number of threads that can be doing a WaitOne on the upgradeEvent (at most 1).
private uint _numUpgradeWaiters;
private WaiterStates _waiterStates;
private int _upgradeLockOwnerId;
private int _writeLockOwnerId;
- // conditions we wait on.
+ // conditions we wait on.
private EventWaitHandle? _writeEvent; // threads waiting to acquire a write lock go here.
private EventWaitHandle? _readEvent; // threads waiting to acquire a read lock go here (will be released in bulk)
private EventWaitHandle? _upgradeEvent; // thread waiting to acquire the upgrade lock
private const int MaxSpinCount = 20;
- //The uint, that contains info like if the writer lock is held, num of
+ //The uint, that contains info like if the writer lock is held, num of
//readers etc.
private uint _owners;
//Writer-Owned Waiting-Writers Waiting Upgraders Num-Readers
// 31 30 29 28.......0
//
- //Dividing the uint, allows to vastly simplify logic for checking if a
+ //Dividing the uint, allows to vastly simplify logic for checking if a
//reader should go in etc. Setting the writer bit will automatically
- //make the value of the uint much larger than the max num of readers
- //allowed, thus causing the check for max_readers to fail.
+ //make the value of the uint much larger than the max num of readers
+ //allowed, thus causing the check for max_readers to fail.
private const uint WRITER_HELD = 0x80000000;
private const uint WAITING_WRITERS = 0x40000000;
/// <summary>
/// This routine retrieves/sets the per-thread counts needed to enforce the
- /// various rules related to acquiring the lock.
- ///
+ /// various rules related to acquiring the lock.
+ ///
/// DontAllocate is set to true if the caller just wants to get an existing
/// entry for this thread, but doesn't want to add one if an existing one
/// could not be found.
lrwc = GetThreadRWCount(dontAllocate: false)!;
//Check if the reader lock is already acquired. Note, we could
- //check the presence of a reader by not allocating rwc (But that
+ //check the presence of a reader by not allocating rwc (But that
//would lead to two lookups in the common case. It's better to keep
//a count in the structure).
if (lrwc.readercount > 0)
for (; ;)
{
// We can enter a read lock if there are only read-locks have been given out
- // and a writer is not trying to get in.
+ // and a writer is not trying to get in.
if (_owners < MAX_READER)
{
continue;
}
- // Drat, we need to wait. Mark that we have waiters and wait.
- if (_readEvent == null) // Create the needed event
+ // Drat, we need to wait. Mark that we have waiters and wait.
+ if (_readEvent == null) // Create the needed event
{
LazyCreateEvent(ref _readEvent, EnterLockType.Read);
if (IsRwHashEntryChanged(lrwc))
lrwc = GetThreadRWCount(dontAllocate: false)!;
- continue; // since we left the lock, start over.
+ continue; // since we left the lock, start over.
}
retVal = WaitOnEvent(_readEvent, ref _numReadWaiters, timeout, EnterLockType.Read);
lrwc = GetThreadRWCount(dontAllocate: true);
- //Can't acquire write lock with reader lock held.
+ //Can't acquire write lock with reader lock held.
if (lrwc != null && lrwc.readercount > 0)
{
_spinLock.Exit();
}
//Check if there is just one upgrader, and no readers.
- //Assumption: Only one thread can have the upgrade lock, so the
- //following check will fail for all other threads that may sneak in
+ //Assumption: Only one thread can have the upgrade lock, so the
+ //following check will fail for all other threads that may sneak in
//when the upgrading thread is waiting.
if (upgradingToWrite)
if (_waitUpgradeEvent == null) // Create the needed event
{
LazyCreateEvent(ref _waitUpgradeEvent, EnterLockType.UpgradeToWrite);
- continue; // since we left the lock, start over.
+ continue; // since we left the lock, start over.
}
Debug.Assert(_numWriteUpgradeWaiters == 0, "There can be at most one thread with the upgrade lock held.");
if (_writeEvent == null) // create the needed event.
{
LazyCreateEvent(ref _writeEvent, EnterLockType.Write);
- continue; // since we left the lock, start over.
+ continue; // since we left the lock, start over.
}
retVal = WaitOnEvent(_writeEvent, ref _numWriteWaiters, timeout, EnterLockType.Write);
_spinLock.Enter(EnterSpinLockReason.EnterAnyRead);
lrwc = GetThreadRWCount(dontAllocate: true);
- //Can't acquire upgrade lock with reader lock held.
+ //Can't acquire upgrade lock with reader lock held.
if (lrwc != null && lrwc.readercount > 0)
{
_spinLock.Exit();
}
else if (id == _writeLockOwnerId)
{
- //Write lock is already held, Just update the global state
+ //Write lock is already held, Just update the global state
//to show presence of upgrader.
Debug.Assert((_owners & WRITER_HELD) > 0);
_owners++;
else if (lrwc.readercount > 0)
{
//Upgrade locks may not be acquired if only read locks have been
- //acquired.
+ //acquired.
_spinLock.Exit();
throw new LockRecursionException(SR.LockRecursionException_UpgradeAfterReadNotAllowed);
}
for (; ;)
{
//Once an upgrade lock is taken, it's like having a reader lock held
- //until upgrade or downgrade operations are performed.
+ //until upgrade or downgrade operations are performed.
if ((_upgradeLockOwnerId == -1) && (_owners < MAX_READER))
{
continue;
}
- // Drat, we need to wait. Mark that we have waiters and wait.
+ // Drat, we need to wait. Mark that we have waiters and wait.
if (_upgradeEvent == null) // Create the needed event
{
LazyCreateEvent(ref _upgradeEvent, EnterLockType.UpgradeableRead);
- continue; // since we left the lock, start over.
+ continue; // since we left the lock, start over.
}
//Only one thread with the upgrade lock held can proceed.
/// A routine for lazily creating a event outside the lock (so if errors
/// happen they are outside the lock and that we don't do much work
/// while holding a spin lock). If all goes well, reenter the lock and
- /// set 'waitEvent'
+ /// set 'waitEvent'
/// </summary>
private void LazyCreateEvent([NotNull] ref EventWaitHandle? waitEvent, EnterLockType enterLockType)
{
}
_spinLock.Enter(enterMyLockReason);
- if (waitEvent == null) // maybe someone snuck in.
+ if (waitEvent == null) // maybe someone snuck in.
waitEvent = newEvent;
else
newEvent.Dispose();
}
/// <summary>
- /// Waits on 'waitEvent' with a timeout
+ /// Waits on 'waitEvent' with a timeout
/// Before the wait 'numWaiters' is incremented and is restored before leaving this routine.
/// </summary>
private bool WaitOnEvent(
}
/// <summary>
- /// Determines the appropriate events to set, leaves the locks, and sets the events.
+ /// Determines the appropriate events to set, leaves the locks, and sets the events.
/// </summary>
private void ExitAndWakeUpAppropriateWaiters()
{
if (readercount == 1 && _numWriteUpgradeWaiters > 0)
{
- //We have to be careful now, as we are dropping the lock.
+ //We have to be careful now, as we are dropping the lock.
//No new writes should be allowed to sneak in if an upgrade
//was pending.
/// Used to deprioritize threads attempting to enter the lock when they would not make progress after doing so.
/// <see cref="EnterSpin(EnterSpinLockReason)"/> avoids acquiring the lock as long as the operation for which it
/// was called is deprioritized.
- ///
+ ///
/// Layout:
/// - Low 16 bits: Number of threads that have deprioritized an enter-any-write operation
/// - High 16 bits: Number of threads that have deprioritized an enter-any-read operation
-// Licensed to the .NET Foundation under one or more agreements.
+// 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.
// Its value must be between the maximum semaphore value and zero
private volatile int m_currentCount;
- // The maximum semaphore value, it is initialized to Int.MaxValue if the client didn't specify it. it is used
+ // The maximum semaphore value, it is initialized to Int.MaxValue if the client didn't specify it. it is used
// to check if the count excceeded the maxi value or not.
private readonly int m_maxCount;
/// <summary>
/// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>,
- /// using a 32-bit signed integer to measure the time interval,
+ /// using a 32-bit signed integer to measure the time interval,
/// while observing a <see cref="T:System.Threading.CancellationToken"/>.
/// </summary>
/// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see cref="Timeout.Infinite"/>(-1) to
}
// If there are any async waiters, for fairness we'll get in line behind
- // then by translating our synchronous wait into an asynchronous one that we
+ // then by translating our synchronous wait into an asynchronous one that we
// then block on (once we've released the lock).
if (m_asyncHead != null)
{
/// The number of milliseconds to wait, or <see cref="Timeout.Infinite"/>(-1) to wait indefinitely.
/// </param>
/// <returns>
- /// A task that will complete with a result of true if the current thread successfully entered
+ /// A task that will complete with a result of true if the current thread successfully entered
/// the <see cref="SemaphoreSlim"/>, otherwise with a result of false.
/// </returns>
/// <exception cref="T:System.ObjectDisposedException">The current instance has already been
/// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
/// </param>
/// <returns>
- /// A task that will complete with a result of true if the current thread successfully entered
+ /// A task that will complete with a result of true if the current thread successfully entered
/// the <see cref="SemaphoreSlim"/>, otherwise with a result of false.
/// </returns>
/// <exception cref="T:System.ObjectDisposedException">
/// The current instance has already been disposed.
/// </exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
- /// <paramref name="timeout"/> is a negative number other than -1 milliseconds, which represents
+ /// <paramref name="timeout"/> is a negative number other than -1 milliseconds, which represents
/// an infinite time-out -or- timeout is greater than <see cref="System.Int32.MaxValue"/>.
/// </exception>
public Task<bool> WaitAsync(TimeSpan timeout)
/// The <see cref="T:System.Threading.CancellationToken"/> token to observe.
/// </param>
/// <returns>
- /// A task that will complete with a result of true if the current thread successfully entered
+ /// A task that will complete with a result of true if the current thread successfully entered
/// the <see cref="SemaphoreSlim"/>, otherwise with a result of false.
/// </returns>
/// <exception cref="T:System.ArgumentOutOfRangeException">
- /// <paramref name="timeout"/> is a negative number other than -1 milliseconds, which represents
+ /// <paramref name="timeout"/> is a negative number other than -1 milliseconds, which represents
/// an infinite time-out -or- timeout is greater than <see cref="System.Int32.MaxValue"/>.
/// </exception>
public Task<bool> WaitAsync(TimeSpan timeout, CancellationToken cancellationToken)
/// <summary>
/// Asynchronously waits to enter the <see cref="SemaphoreSlim"/>,
- /// using a 32-bit signed integer to measure the time interval,
+ /// using a 32-bit signed integer to measure the time interval,
/// while observing a <see cref="T:System.Threading.CancellationToken"/>.
/// </summary>
/// <param name="millisecondsTimeout">
/// </param>
/// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to observe.</param>
/// <returns>
- /// A task that will complete with a result of true if the current thread successfully entered
+ /// A task that will complete with a result of true if the current thread successfully entered
/// the <see cref="SemaphoreSlim"/>, otherwise with a result of false.
/// </returns>
/// <exception cref="T:System.ObjectDisposedException">The current instance has already been
}
/// <summary>
- /// When overridden in a derived class, releases the unmanaged resources used by the
+ /// When overridden in a derived class, releases the unmanaged resources used by the
/// <see cref="T:System.Threading.ManualResetEventSlim"/>, and optionally releases the managed resources.
/// </summary>
/// <param name="disposing">true to release both managed and unmanaged resources;
//
// A spin lock is a mutual exclusion lock primitive where a thread trying to acquire the lock waits in a loop ("spins")
// repeatedly checking until the lock becomes available. As the thread remains active performing a non-useful task,
-// the use of such a lock is a kind of busy waiting and consumes CPU resources without performing real work.
+// the use of such a lock is a kind of busy waiting and consumes CPU resources without performing real work.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// 1) Ownership tracking enabled: the high bit is 0, and the remaining bits
// store the managed thread ID of the current owner. When the 31 low bits
// are 0, the lock is available.
- // 2) Performance mode: when the high bit is 1, lock availability is indicated by the low bit.
+ // 2) Performance mode: when the high bit is 1, lock availability is indicated by the low bit.
// When the low bit is 1 -- the lock is held; 0 -- the lock is available.
//
// There are several masks and constants below for convenience.
}
/// <summary>Gets whether thread ownership tracking is enabled for this instance.</summary>
- public bool IsThreadOwnerTrackingEnabled => (_owner & LOCK_ID_DISABLE_MASK) == 0;
+ public bool IsThreadOwnerTrackingEnabled => (_owner & LOCK_ID_DISABLE_MASK) == 0;
#region Debugger proxy class
/// <summary>
- /// Internal class used by debug type proxy attribute to display the owner thread ID
+ /// Internal class used by debug type proxy attribute to display the owner thread ID
/// </summary>
internal class SystemThreading_SpinLockDebugView
{
// }
//
// Internally it just maintains a counter that is used to decide when to yield, etc.
- //
+ //
// A common usage is to spin before blocking. In those cases, the NextSpinWillYield
// property allows a user to decide to fall back to waiting once it returns true:
- //
+ //
// void f() {
// SpinWait wait = new SpinWait();
// while (!p) {
/// <remarks>
/// These numbers were arrived at by experimenting with different numbers in various cases that currently use it. It's
/// only a suggested value and typically works well when the proper wait is something like an event.
- ///
+ ///
/// Spinning less can lead to early waiting and more context switching, spinning more can decrease latency but may use
/// up some CPU time unnecessarily. Depends on the situation too, for instance SemaphoreSlim uses more iterations
/// because the waiting there is currently a lot more expensive (involves more spinning, taking a lock, etc.). It also
/// </summary>
/// <param name="condition">A delegate to be executed over and over until it returns true.</param>
/// <param name="timeout">
- /// A <see cref="TimeSpan"/> that represents the number of milliseconds to wait,
+ /// A <see cref="TimeSpan"/> that represents the number of milliseconds to wait,
/// or a TimeSpan that represents -1 milliseconds to wait indefinitely.</param>
/// <returns>True if the condition is satisfied within the timeout; otherwise, false</returns>
/// <exception cref="ArgumentNullException">The <paramref name="condition"/> argument is null.</exception>
//
//
//
-// A pair of schedulers that together support concurrent (reader) / exclusive (writer)
+// A pair of schedulers that together support concurrent (reader) / exclusive (writer)
// task scheduling. Using just the exclusive scheduler can be used to simulate a serial
-// processing queue, and using just the concurrent scheduler with a specified
+// processing queue, and using just the concurrent scheduler with a specified
// MaximumConcurrentlyLevel can be used to achieve a MaxDegreeOfParallelism across
// a bunch of tasks, parallel loops, dataflow blocks, etc.
//
/// <summary>The underlying task scheduler to which all work should be scheduled.</summary>
private readonly TaskScheduler m_underlyingTaskScheduler;
/// <summary>
- /// The maximum number of tasks allowed to run concurrently. This only applies to concurrent tasks,
+ /// The maximum number of tasks allowed to run concurrently. This only applies to concurrent tasks,
/// since exclusive tasks are inherently limited to 1.
/// </summary>
private readonly int m_maxConcurrencyLevel;
{ }
/// <summary>
- /// Initializes the ConcurrentExclusiveSchedulerPair to target the specified scheduler with a maximum
+ /// Initializes the ConcurrentExclusiveSchedulerPair to target the specified scheduler with a maximum
/// concurrency level and a maximum number of scheduled tasks that may be processed as a unit.
/// </summary>
/// <param name="taskScheduler">The target scheduler on which this pair should execute.</param>
{
// We snap whether there are any exclusive tasks or concurrent tasks waiting.
// (We grab the concurrent count below only once we know we need it.)
- // With processing happening concurrent to this operation, this data may
+ // With processing happening concurrent to this operation, this data may
// immediately be out of date, but it can only go from non-empty
- // to empty and not the other way around. As such, this is safe,
+ // to empty and not the other way around. As such, this is safe,
// as worst case is we'll schedule an extra task when we didn't
// otherwise need to, and we'll just eat its overhead.
bool exclusiveTasksAreWaiting = !m_exclusiveTaskScheduler.m_tasks.IsEmpty;
// while completion may have been requested, we can't have shutdown yet.
if (!taskWasPreviouslyQueued && m_pair.CompletionRequested) return false;
- // We know the implementation of the default scheduler and how it will behave.
+ // We know the implementation of the default scheduler and how it will behave.
// As it's the most common underlying scheduler, we optimize for it.
bool isDefaultScheduler = m_pair.m_underlyingTaskScheduler == TaskScheduler.Default;
}
/// <summary>
- /// Implements a reasonable approximation for TryExecuteTaskInline on the underlying scheduler,
+ /// Implements a reasonable approximation for TryExecuteTaskInline on the underlying scheduler,
/// which we can't call directly on the underlying scheduler.
/// </summary>
/// <param name="task">The task to execute inline if possible.</param>
/// purposes. For example, to create a <see cref="Task{TResult}"/> that runs a function, the factory's StartNew
/// method may be used:
/// <code>
- /// // C#
+ /// // C#
/// var t = Task<int>.Factory.StartNew(() => GenerateResult());
/// - or -
/// var t = Task.Factory.StartNew(() => GenerateResult());
- ///
- /// ' Visual Basic
+ ///
+ /// ' Visual Basic
/// Dim t = Task<int>.Factory.StartNew(Function() GenerateResult())
/// - or -
/// Dim t = Task.Factory.StartNew(Function() GenerateResult())
/// The <see cref="Task{TResult}"/> class also provides constructors that initialize the task but that do not
/// schedule it for execution. For performance reasons, the StartNew method should be the
/// preferred mechanism for creating and scheduling computational tasks, but for scenarios where creation
- /// and scheduling must be separated, the constructors may be used, and the task's
+ /// and scheduling must be separated, the constructors may be used, and the task's
/// <see cref="System.Threading.Tasks.Task.Start()">Start</see>
/// method may then be used to schedule the task for execution at a later time.
/// </para>
/// <para>
- /// All members of <see cref="Task{TResult}"/>, except for
+ /// All members of <see cref="Task{TResult}"/>, except for
/// <see cref="System.Threading.Tasks.Task.Dispose()">Dispose</see>, are thread-safe
/// and may be used from multiple threads concurrently.
/// </para>
{
}
- // Construct a promise-style task with state and options.
+ // Construct a promise-style task with state and options.
internal Task(object? state, TaskCreationOptions options) :
base(state, options, promiseStyle: true)
{
bool returnValue = false;
// "Reserve" the completion for this task, while making sure that: (1) No prior reservation
- // has been made, (2) The result has not already been set, (3) An exception has not previously
+ // has been made, (2) The result has not already been set, (3) An exception has not previously
// been recorded, and (4) Cancellation has not been requested.
//
// If the reservation is successful, then set the result and finish completion processing.
/// <summary>
/// Evaluates the value selector of the Task which is passed in as an object and stores the result.
- /// </summary>
+ /// </summary>
internal override void InnerInvoke()
{
// Invoke the delegate
/// Provides support for creating and scheduling
/// <see cref="T:System.Threading.Tasks.Task{TResult}">Task{TResult}</see> objects.
/// </summary>
- /// <typeparam name="TResult">The type of the results that are available though
- /// the <see cref="T:System.Threading.Tasks.Task{TResult}">Task{TResult}</see> objects that are associated with
+ /// <typeparam name="TResult">The type of the results that are available though
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}">Task{TResult}</see> objects that are associated with
/// the methods in this class.</typeparam>
/// <remarks>
/// <para>
/// </remarks>
public class TaskFactory<TResult>
{
- // Member variables, DefaultScheduler, other properties and ctors
+ // Member variables, DefaultScheduler, other properties and ctors
// copied right out of TaskFactory... Lots of duplication here...
// Should we be thinking about a TaskFactoryBase class?
/// <summary>
/// Initializes a <see cref="TaskFactory{TResult}"/> instance with the default configuration.
/// </summary>
- /// <param name="cancellationToken">The default <see cref="CancellationToken"/> that will be assigned
- /// to tasks created by this <see cref="TaskFactory"/> unless another CancellationToken is explicitly specified
+ /// <param name="cancellationToken">The default <see cref="CancellationToken"/> that will be assigned
+ /// to tasks created by this <see cref="TaskFactory"/> unless another CancellationToken is explicitly specified
/// while calling the factory methods.</param>
/// <remarks>
/// This constructor creates a <see cref="TaskFactory{TResult}"/> instance with a default configuration. The
/// <summary>
/// Initializes a <see cref="TaskFactory{TResult}"/> instance with the specified configuration.
/// </summary>
- /// <param name="cancellationToken">The default <see cref="CancellationToken"/> that will be assigned
- /// to tasks created by this <see cref="TaskFactory"/> unless another CancellationToken is explicitly specified
+ /// <param name="cancellationToken">The default <see cref="CancellationToken"/> that will be assigned
+ /// to tasks created by this <see cref="TaskFactory"/> unless another CancellationToken is explicitly specified
/// while calling the factory methods.</param>
/// <param name="creationOptions">
/// The default <see cref="System.Threading.Tasks.TaskCreationOptions">
/// TaskFactory.
/// </summary>
/// <remarks>
- /// This property returns the default <see cref="CancellationToken"/> that will be assigned to all
- /// tasks created by this factory unless another CancellationToken value is explicitly specified
+ /// This property returns the default <see cref="CancellationToken"/> that will be assigned to all
+ /// tasks created by this factory unless another CancellationToken value is explicitly specified
/// during the call to the factory methods.
/// </remarks>
public CancellationToken CancellationToken { get { return m_defaultCancellationToken; } }
/// TaskFactory{TResult}.
/// </summary>
/// <remarks>
- /// This property returns the default scheduler for this factory. It will be used to schedule all
- /// tasks unless another scheduler is explicitly specified during calls to this factory's methods.
- /// If null, <see cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>
+ /// This property returns the default scheduler for this factory. It will be used to schedule all
+ /// tasks unless another scheduler is explicitly specified during calls to this factory's methods.
+ /// If null, <see cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>
/// will be used.
/// </remarks>
public TaskScheduler? Scheduler { get { return m_defaultScheduler; } }
/// </see> value of this TaskFactory{TResult}.
/// </summary>
/// <remarks>
- /// This property returns the default creation options for this factory. They will be used to create all
+ /// This property returns the default creation options for this factory. They will be used to create all
/// tasks unless other options are explicitly specified during calls to this factory's methods.
/// </remarks>
public TaskCreationOptions CreationOptions { get { return m_defaultCreationOptions; } }
/// </see> value of this TaskFactory{TResult}.
/// </summary>
/// <remarks>
- /// This property returns the default continuation options for this factory. They will be used to create
+ /// This property returns the default continuation options for this factory. They will be used to create
/// all continuation tasks unless other options are explicitly specified during calls to this factory's methods.
/// </remarks>
public TaskContinuationOptions ContinuationOptions { get { return m_defaultContinuationOptions; } }
if (Task.s_asyncDebuggingEnabled)
Task.AddToActiveTasks(promise);
- // Just specify this task as detached. No matter what happens, we want endMethod
- // to be called -- even if the parent is canceled. So we don't want to flow
+ // Just specify this task as detached. No matter what happens, we want endMethod
+ // to be called -- even if the parent is canceled. So we don't want to flow
// RespectParentCancellation.
Task t = new Task(new Action<object>(delegate
{
}
/// <summary>
- /// Completes the asynchronous operation using information in the IAsyncResult.
+ /// Completes the asynchronous operation using information in the IAsyncResult.
/// IAsyncResult.AsyncState needs to be the FromAsyncTrimPromise to complete.
/// </summary>
/// <param name="asyncResult">The IAsyncResult for the async operation.</param>
//
/// <summary>
- /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
/// that will be started upon the completion of a set of provided Tasks.
/// </summary>
/// <param name="tasks">The array of tasks from which to continue.</param>
- /// <param name="continuationFunction">The function delegate to execute when all tasks in
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in
/// the <paramref name="tasks"/> array have completed.</param>
/// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="tasks"/> array is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="continuationFunction"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array contains a null value.</exception>
- /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
public Task<TResult> ContinueWhenAll(Task[] tasks, Func<Task[], TResult> continuationFunction)
{
}
/// <summary>
- /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
/// that will be started upon the completion of a set of provided Tasks.
/// </summary>
/// <param name="tasks">The array of tasks from which to continue.</param>
- /// <param name="continuationFunction">The function delegate to execute when all tasks in
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in
/// the <paramref name="tasks"/> array have completed.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="tasks"/> array is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="continuationFunction"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array contains a null value.</exception>
- /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
/// value.</exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
public Task<TResult> ContinueWhenAll(Task[] tasks, Func<Task[], TResult> continuationFunction, TaskContinuationOptions continuationOptions)
/// <param name="tasks">The array of tasks from which to continue.</param>
/// <param name="continuationFunction">The function delegate to execute when all tasks in the <paramref
/// name="tasks"/> array have completed.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
/// TaskContinuationOptions</see> value that controls the behavior of
/// has already been disposed.
/// </exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
public Task<TResult> ContinueWhenAll(Task[] tasks, Func<Task[], TResult> continuationFunction,
/// <param name="tasks">The array of tasks from which to continue.</param>
/// <param name="continuationFunction">The function delegate to execute when all tasks in the
/// <paramref name="tasks"/> array have completed.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
/// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
/// value.</exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
public Task<TResult> ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
/// <param name="tasks">The array of tasks from which to continue.</param>
/// <param name="continuationFunction">The function delegate to execute when all tasks in the
/// <paramref name="tasks"/> array have completed.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
/// TaskContinuationOptions</see> value that controls the behavior of
/// has already been disposed.
/// </exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
public Task<TResult> ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
// Core implementation of ContinueWhenAll -- the generic version
- // Note: if you make any changes to this method, please do the same to the non-generic version too.
+ // Note: if you make any changes to this method, please do the same to the non-generic version too.
internal static Task<TResult> ContinueWhenAllImpl<TAntecedentResult>(Task<TAntecedentResult>[] tasks,
Func<Task<TAntecedentResult>[], TResult>? continuationFunction, Action<Task<TAntecedentResult>[]>? continuationAction,
TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler)
}
// Core implementation of ContinueWhenAll -- the non-generic version
- // Note: if you make any changes to this method, please do the same to the generic version too.
+ // Note: if you make any changes to this method, please do the same to the generic version too.
internal static Task<TResult> ContinueWhenAllImpl(Task[] tasks,
Func<Task[], TResult>? continuationFunction, Action<Task[]>? continuationAction,
TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler)
/// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
/// <param name="continuationFunction">The function delegate to execute when one task in the <paramref
/// name="tasks"/> array completes.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
/// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
/// value.</exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
public Task<TResult> ContinueWhenAny(Task[] tasks, Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions)
/// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
/// <param name="continuationFunction">The function delegate to execute when one task in the <paramref
/// name="tasks"/> array completes.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
/// TaskContinuationOptions</see> value that controls the behavior of
/// has already been disposed.
/// </exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
public Task<TResult> ContinueWhenAny(Task[] tasks, Func<Task, TResult> continuationFunction,
/// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
/// <param name="continuationFunction">The function delegate to execute when one task in the
/// <paramref name="tasks"/> array completes.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
/// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
/// value.</exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
public Task<TResult> ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
/// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
/// <param name="continuationFunction">The function delegate to execute when one task in the
/// <paramref name="tasks"/> array completes.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
/// TaskContinuationOptions</see> value that controls the behavior of
/// has already been disposed.
/// </exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
public Task<TResult> ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
}
// Core implementation of ContinueWhenAny, non-generic version
- // Note: if you make any changes to this method, be sure to do the same to the generic version
+ // Note: if you make any changes to this method, be sure to do the same to the generic version
internal static Task<TResult> ContinueWhenAnyImpl(Task[] tasks,
Func<Task, TResult>? continuationFunction, Action<Task>? continuationAction,
TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler)
// Core implementation of ContinueWhenAny, generic version
- // Note: if you make any changes to this method, be sure to do the same to the non-generic version
+ // Note: if you make any changes to this method, be sure to do the same to the non-generic version
internal static Task<TResult> ContinueWhenAnyImpl<TAntecedentResult>(Task<TAntecedentResult>[] tasks,
Func<Task<TAntecedentResult>, TResult>? continuationFunction, Action<Task<TAntecedentResult>>? continuationAction,
TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler)
{
// Design:
//
- // SingleProducerSingleConsumerQueue (SPSCQueue) is a concurrent queue designed to be used
- // by one producer thread and one consumer thread. SPSCQueue does not work correctly when used by
+ // SingleProducerSingleConsumerQueue (SPSCQueue) is a concurrent queue designed to be used
+ // by one producer thread and one consumer thread. SPSCQueue does not work correctly when used by
// multiple producer threads concurrently or multiple consumer threads concurrently.
- //
- // SPSCQueue is based on segments that behave like circular buffers. Each circular buffer is represented
- // as an array with two indexes: m_first and m_last. m_first is the index of the array slot for the consumer
- // to read next, and m_last is the slot for the producer to write next. The circular buffer is empty when
+ //
+ // SPSCQueue is based on segments that behave like circular buffers. Each circular buffer is represented
+ // as an array with two indexes: m_first and m_last. m_first is the index of the array slot for the consumer
+ // to read next, and m_last is the slot for the producer to write next. The circular buffer is empty when
// (m_first == m_last), and full when ((m_last+1) % m_array.Length == m_first).
//
- // Since m_first is only ever modified by the consumer thread and m_last by the producer, the two indices can
- // be updated without interlocked operations. As long as the queue size fits inside a single circular buffer,
- // enqueues and dequeues simply advance the corresponding indices around the circular buffer. If an enqueue finds
- // that there is no room in the existing buffer, however, a new circular buffer is allocated that is twice as big
- // as the old buffer. From then on, the producer will insert values into the new buffer. The consumer will first
+ // Since m_first is only ever modified by the consumer thread and m_last by the producer, the two indices can
+ // be updated without interlocked operations. As long as the queue size fits inside a single circular buffer,
+ // enqueues and dequeues simply advance the corresponding indices around the circular buffer. If an enqueue finds
+ // that there is no room in the existing buffer, however, a new circular buffer is allocated that is twice as big
+ // as the old buffer. From then on, the producer will insert values into the new buffer. The consumer will first
// empty out the old buffer and only then follow the producer into the new (larger) buffer.
//
- // As described above, the enqueue operation on the fast path only modifies the m_first field of the current segment.
- // However, it also needs to read m_last in order to verify that there is room in the current segment. Similarly, the
- // dequeue operation on the fast path only needs to modify m_last, but also needs to read m_first to verify that the
+ // As described above, the enqueue operation on the fast path only modifies the m_first field of the current segment.
+ // However, it also needs to read m_last in order to verify that there is room in the current segment. Similarly, the
+ // dequeue operation on the fast path only needs to modify m_last, but also needs to read m_first to verify that the
// queue is non-empty. This results in true cache line sharing between the producer and the consumer.
//
- // The cache line sharing issue can be mitigating by having a possibly stale copy of m_first that is owned by the producer,
- // and a possibly stale copy of m_last that is owned by the consumer. So, the consumer state is described using
- // (m_first, m_lastCopy) and the producer state using (m_firstCopy, m_last). The consumer state is separated from
- // the producer state by padding, which allows fast-path enqueues and dequeues from hitting shared cache lines.
- // m_lastCopy is the consumer's copy of m_last. Whenever the consumer can tell that there is room in the buffer
- // simply by observing m_lastCopy, the consumer thread does not need to read m_last and thus encounter a cache miss. Only
- // when the buffer appears to be empty will the consumer refresh m_lastCopy from m_last. m_firstCopy is used by the producer
+ // The cache line sharing issue can be mitigating by having a possibly stale copy of m_first that is owned by the producer,
+ // and a possibly stale copy of m_last that is owned by the consumer. So, the consumer state is described using
+ // (m_first, m_lastCopy) and the producer state using (m_firstCopy, m_last). The consumer state is separated from
+ // the producer state by padding, which allows fast-path enqueues and dequeues from hitting shared cache lines.
+ // m_lastCopy is the consumer's copy of m_last. Whenever the consumer can tell that there is room in the buffer
+ // simply by observing m_lastCopy, the consumer thread does not need to read m_last and thus encounter a cache miss. Only
+ // when the buffer appears to be empty will the consumer refresh m_lastCopy from m_last. m_firstCopy is used by the producer
// in the same way to avoid reading m_first on the hot path.
/// <summary>The initial size to use for segments (in number of elements).</summary>
try { }
finally
{
- // Finally block to protect against corruption due to a thread abort
+ // Finally block to protect against corruption due to a thread abort
// between setting m_next and setting m_tail.
Volatile.Write(ref m_tail.m_next, newSegment); // ensure segment not published until item is fully stored
m_tail = newSegment;
/// </summary>
public enum TaskStatus
{
- /// <summary>
+ /// <summary>
/// The task has been initialized but has not yet been scheduled.
/// </summary>
Created,
- /// <summary>
+ /// <summary>
/// The task is waiting to be activated and scheduled internally by the .NET Framework infrastructure.
/// </summary>
WaitingForActivation,
/// purposes. For example, to create a <see cref="Task"/> that runs an action, the factory's StartNew
/// method may be used:
/// <code>
- /// // C#
+ /// // C#
/// var t = Task.Factory.StartNew(() => DoAction());
- ///
- /// ' Visual Basic
+ ///
+ /// ' Visual Basic
/// Dim t = Task.Factory.StartNew(Function() DoAction())
/// </code>
/// </para>
internal Delegate? m_action; // The body of the task. Might be Action<object>, Action<TState> or Action. Or possibly a Func.
// If m_action is set to null it will indicate that we operate in the
- // "externally triggered completion" mode, which is exclusively meant
+ // "externally triggered completion" mode, which is exclusively meant
// for the signalling Task<TResult> (aka. promise). In this mode,
// we don't call InnerInvoke() in response to a Wait(), but simply wait on
// the completion event which will be set when the Future class calls Finish().
internal object? m_stateObject; // A state object that can be optionally supplied, passed to action.
- internal TaskScheduler? m_taskScheduler; // The task scheduler this task runs under.
+ internal TaskScheduler? m_taskScheduler; // The task scheduler this task runs under.
internal volatile int m_stateFlags; // SOS DumpAsync command depends on this name
tmpFlags | TASK_STATE_WAITINGFORACTIVATION :
tmpFlags;
- // Now is the time to add the new task to the children list
+ // Now is the time to add the new task to the children list
// of the creating task if the options call for it.
- // We can safely call the creator task's AddNewChild() method to register it,
+ // We can safely call the creator task's AddNewChild() method to register it,
// because at this point we are already on its thread of execution.
ContingentProperties? props = m_contingentProperties;
try
{
// If an unstarted task has a valid CancellationToken that gets signalled while the task is still not queued
- // we need to proactively cancel it, because it may never execute to transition itself.
+ // we need to proactively cancel it, because it may never execute to transition itself.
// The only way to accomplish this is to register a callback on the CT.
- // We exclude Promise tasks from this, because TaskCompletionSource needs to fully control the inner tasks's lifetime (i.e. not allow external cancellations)
+ // We exclude Promise tasks from this, because TaskCompletionSource needs to fully control the inner tasks's lifetime (i.e. not allow external cancellations)
if ((((InternalTaskOptions)Options &
(InternalTaskOptions.QueuedByRuntime | InternalTaskOptions.PromiseTask | InternalTaskOptions.LazyCancellation)) == 0))
{
{
Debug.Assert(continuation != null);
- // If an antecedent was specified, pack this task, its antecedent and the TaskContinuation together as a tuple
- // and use it as the cancellation state object. This will be unpacked in the cancellation callback so that
+ // If an antecedent was specified, pack this task, its antecedent and the TaskContinuation together as a tuple
+ // and use it as the cancellation state object. This will be unpacked in the cancellation callback so that
// antecedent.RemoveCancellation(continuation) can be invoked.
ctr = cancellationToken.UnsafeRegister(t =>
{
var tuple = (Tuple<Task, Task, TaskContinuation>)t!;
-
+
Task targetTask = tuple.Item1;
Task antecedentTask = tuple.Item2;
}
/// <summary>
- /// Determines whether we should inform the debugger that we're ending a join with a task.
+ /// Determines whether we should inform the debugger that we're ending a join with a task.
/// This should only be called if the debugger notification bit is set, as it is has some cost,
- /// namely it is a virtual call (however calling it if the bit is not set is not functionally
- /// harmful). Derived implementations may choose to only conditionally call down to this base
+ /// namely it is a virtual call (however calling it if the bit is not set is not functionally
+ /// harmful). Derived implementations may choose to only conditionally call down to this base
/// implementation.
/// </summary>
internal virtual bool ShouldNotifyDebuggerOfWaitCompletion // ideally would be familyAndAssembly, but that can't be done in C#
{
get
{
- // It's theoretically possible but extremely rare that this assert could fire because the
+ // It's theoretically possible but extremely rare that this assert could fire because the
// bit was unset between the time that it was checked and this method was called.
// It's so remote a chance that it's worth having the assert to protect against misuse.
bool isWaitNotificationEnabled = IsWaitNotificationEnabled;
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
private void NotifyDebuggerOfWaitCompletion()
{
- // It's theoretically possible but extremely rare that this assert could fire because the
+ // It's theoretically possible but extremely rare that this assert could fire because the
// bit was unset between the time that it was checked and this method was called.
// It's so remote a chance that it's worth having the assert to protect against misuse.
Debug.Assert(IsWaitNotificationEnabled, "Should only be called if the wait completion bit is set.");
// Now that we're notifying the debugger, clear the bit. The debugger should do this anyway,
- // but this adds a bit of protection in case it fails to, and given that the debugger is involved,
+ // but this adds a bit of protection in case it fails to, and given that the debugger is involved,
// the overhead here for the interlocked is negligable. We do still rely on the debugger
// to clear bits, as this doesn't recursively clear bits in the case of, for example, WhenAny.
SetNotificationForWaitCompletion(enabled: false);
}
/// <summary>
- /// Internal function that will be called by a new child task to add itself to
+ /// Internal function that will be called by a new child task to add itself to
/// the children list of the parent (this).
- ///
+ ///
/// Since a child task can only be created from the thread executing the action delegate
/// of this task, reentrancy is neither required nor supported. This should not be called from
/// anywhere other than the task construction/initialization codepaths.
//
// Internal version of RunSynchronously that allows not waiting for completion.
- //
+ //
internal void InternalRunSynchronously(TaskScheduler scheduler, bool waitForCompletion)
{
Debug.Assert(scheduler != null, "Task.InternalRunSynchronously(): null TaskScheduler");
// we received an unexpected exception originating from a custom scheduler, which needs to be wrapped in a TSE and thrown
if (!taskQueued)
{
- // We had a problem with TryRunInline() or QueueTask().
+ // We had a problem with TryRunInline() or QueueTask().
// Record the exception, marking ourselves as Completed/Faulted.
TaskSchedulerException tse = new TaskSchedulerException(e);
AddException(tse);
}
/// <summary>
- /// Gets the <see cref="T:System.Threading.Tasks.TaskStatus">TaskStatus</see> of this Task.
+ /// Gets the <see cref="T:System.Threading.Tasks.TaskStatus">TaskStatus</see> of this Task.
/// </summary>
public TaskStatus Status
{
/// execution due to being canceled.
/// </summary>
/// <remarks>
- /// A <see cref="Task">Task</see> will complete in Canceled state either if its <see cref="CancellationToken">CancellationToken</see>
- /// was marked for cancellation before the task started executing, or if the task acknowledged the cancellation request on
- /// its already signaled CancellationToken by throwing an
- /// <see cref="System.OperationCanceledException">OperationCanceledException</see> that bears the same
+ /// A <see cref="Task">Task</see> will complete in Canceled state either if its <see cref="CancellationToken">CancellationToken</see>
+ /// was marked for cancellation before the task started executing, or if the task acknowledged the cancellation request on
+ /// its already signaled CancellationToken by throwing an
+ /// <see cref="System.OperationCanceledException">OperationCanceledException</see> that bears the same
/// <see cref="System.Threading.CancellationToken">CancellationToken</see>.
/// </remarks>
public bool IsCanceled
}
/// <summary>
- /// This internal property provides access to the CancellationToken that was set on the task
+ /// This internal property provides access to the CancellationToken that was set on the task
/// when it was constructed.
/// </summary>
internal CancellationToken CancellationToken
/// <summary>
- /// Disposes the <see cref="Task"/>, releasing all of its unmanaged resources.
+ /// Disposes the <see cref="Task"/>, releasing all of its unmanaged resources.
/// </summary>
/// <remarks>
/// Unlike most of the members of <see cref="Task"/>, this method is not thread-safe.
/// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
/// </remarks>
/// <exception cref="T:System.InvalidOperationException">
- /// The exception that is thrown if the <see cref="Task"/> is not in
+ /// The exception that is thrown if the <see cref="Task"/> is not in
/// one of the final states: <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
/// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
/// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
- /// </exception>
+ /// </exception>
public void Dispose()
{
Dispose(true);
}
/// <summary>
- /// Disposes the <see cref="Task"/>, releasing all of its unmanaged resources.
+ /// Disposes the <see cref="Task"/>, releasing all of its unmanaged resources.
/// </summary>
/// <param name="disposing">
/// A Boolean value that indicates whether this method is being called due to a call to <see
if (disposing)
{
// Dispose is a nop if this task was created with the DoNotDispose internal option.
- // This is done before the completed check, because if we're not touching any
+ // This is done before the completed check, because if we're not touching any
// state on the task, it's ok for it to happen before completion.
if ((Options & (TaskCreationOptions)InternalTaskOptions.DoNotDispose) != 0)
{
// In the unlikely event that our completion event is inflated but not yet signaled,
// go ahead and signal the event. If you dispose of an unsignaled MRES, then any waiters
// will deadlock; an ensuing Set() will not wake them up. In the event of an AppDomainUnload,
- // there is no guarantee that anyone else is going to signal the event, and it does no harm to
+ // there is no guarantee that anyone else is going to signal the event, and it does no harm to
// call Set() twice on m_completionEvent.
if (!ev.IsSet) ev.Set();
//
// -- Task<TResult>.TrySetException(): The lock allows the
// task to be set to Faulted state, and all exceptions to
- // be recorded, in one atomic action.
+ // be recorded, in one atomic action.
//
// -- Task.Exception_get(): The lock ensures that Task<TResult>.TrySetException()
// is allowed to complete its operation before Task.Exception_get()
Exception? canceledException = null;
if (includeTaskCanceledExceptions && IsCanceled)
{
- // Backcompat:
+ // Backcompat:
// Ideally we'd just use the cached OCE from this.GetCancellationExceptionDispatchInfo()
// here. However, that would result in a potentially breaking change from .NET 4, which
// has the code here that throws a new exception instead of the original, and the EDI
}
/// <summary>
- /// Throws an aggregate exception if the task contains exceptions.
+ /// Throws an aggregate exception if the task contains exceptions.
/// </summary>
internal void ThrowIfExceptional(bool includeTaskCanceledExceptions)
{
/// <param name="targetContext">The target context on which to propagate the exception. Null to use the ThreadPool.</param>
internal static void ThrowAsync(Exception exception, SynchronizationContext? targetContext)
{
- // Capture the exception into an ExceptionDispatchInfo so that its
+ // Capture the exception into an ExceptionDispatchInfo so that its
// stack trace and Watson bucket info will be preserved
var edi = ExceptionDispatchInfo.Capture(exception);
}
catch (Exception postException)
{
- // If something goes horribly wrong in the Post, we'll
+ // If something goes horribly wrong in the Post, we'll
// propagate both exceptions on the ThreadPool
edi = ExceptionDispatchInfo.Capture(new AggregateException(exception, postException));
}
/// <summary>
/// Checks whether this is an attached task, and whether we are being called by the parent task.
/// And sets the TASK_STATE_EXCEPTIONOBSERVEDBYPARENT status flag based on that.
- ///
- /// This is meant to be used internally when throwing an exception, and when WaitAll is gathering
- /// exceptions for tasks it waited on. If this flag gets set, the implicit wait on children
+ ///
+ /// This is meant to be used internally when throwing an exception, and when WaitAll is gathering
+ /// exceptions for tasks it waited on. If this flag gets set, the implicit wait on children
/// will skip exceptions to prevent duplication.
- ///
+ ///
/// This should only be called when this task has completed with an exception
- ///
+ ///
/// </summary>
internal void UpdateExceptionObservedStatus()
{
/// <summary>
/// Checks whether the TASK_STATE_EXCEPTIONOBSERVEDBYPARENT status flag is set,
/// This will only be used by the implicit wait to prevent double throws
- ///
+ ///
/// </summary>
internal bool IsExceptionObservedByParent
{
/// Signals completion of this particular task.
///
/// The userDelegateExecute parameter indicates whether this Finish() call comes following the
- /// full execution of the user delegate.
- ///
+ /// full execution of the user delegate.
+ ///
/// If userDelegateExecute is false, it mean user delegate wasn't invoked at all (either due to
/// a cancellation request, or because this task is a promise style Task). In this case, the steps
/// involving child tasks (i.e. WaitForChildren) will be skipped.
- ///
+ ///
/// </summary>
internal void Finish(bool userDelegateExecute)
{
{
ContingentProperties props = m_contingentProperties!;
- // Count of 1 => either all children finished, or there were none. Safe to complete ourselves
+ // Count of 1 => either all children finished, or there were none. Safe to complete ourselves
// without paying the price of an Interlocked.Decrement.
if ((props.m_completionCountdown == 1) ||
Interlocked.Decrement(ref props.m_completionCountdown) == 0) // Reaching this sub clause means there may be remaining active children,
// Apparently some children still remain. It will be up to the last one to process the completion of this task on their own thread.
// We will now yield the thread back to ThreadPool. Mark our state appropriately before getting out.
- // We have to use an atomic update for this and make sure not to overwrite a final state,
+ // We have to use an atomic update for this and make sure not to overwrite a final state,
// because at this very moment the last child's thread may be concurrently completing us.
// Otherwise we risk overwriting the TASK_STATE_RAN_TO_COMPLETION, _CANCELED or _FAULTED bit which may have been set by that child task.
- // Note that the concurrent update by the last child happening in FinishStageTwo could still wipe out the TASK_STATE_WAITING_ON_CHILDREN flag,
+ // Note that the concurrent update by the last child happening in FinishStageTwo could still wipe out the TASK_STATE_WAITING_ON_CHILDREN flag,
// but it is not critical to maintain, therefore we dont' need to intruduce a full atomic update into FinishStageTwo
AtomicStateUpdate(TASK_STATE_WAITING_ON_CHILDREN, TASK_STATE_FAULTED | TASK_STATE_CANCELED | TASK_STATE_RAN_TO_COMPLETION);
}
// Now is the time to prune exceptional children. We'll walk the list and removes the ones whose exceptions we might have observed after they threw.
- // we use a local variable for exceptional children here because some other thread may be nulling out m_contingentProperties.m_exceptionalChildren
+ // we use a local variable for exceptional children here because some other thread may be nulling out m_contingentProperties.m_exceptionalChildren
List<Task>? exceptionalChildren = props.m_exceptionalChildren;
if (exceptionalChildren != null)
{
}
/// <summary>
- /// FinishStageTwo is to be executed as soon as we known there are no more children to complete.
+ /// FinishStageTwo is to be executed as soon as we known there are no more children to complete.
/// It can happen i) either on the thread that originally executed this task (if no children were spawned, or they all completed by the time this task's delegate quit)
/// ii) or on the thread that executed the last child.
/// </summary>
private void FinishStageTwo()
{
// At this point, the task is done executing and waiting for its children,
- // we can transition our task to a completion state.
+ // we can transition our task to a completion state.
ContingentProperties? cp = Volatile.Read(ref m_contingentProperties);
if (cp != null)
}
else if (IsCancellationRequested && IsCancellationAcknowledged)
{
- // We transition into the TASK_STATE_CANCELED final state if the task's CT was signalled for cancellation,
- // and the user delegate acknowledged the cancellation request by throwing an OCE,
+ // We transition into the TASK_STATE_CANCELED final state if the task's CT was signalled for cancellation,
+ // and the user delegate acknowledged the cancellation request by throwing an OCE,
// and the task hasn't otherwise transitioned into faulted state. (TASK_STATE_FAULTED trumps TASK_STATE_CANCELED)
//
// If the task threw an OCE without cancellation being requestsed (while the CT not being in signaled state),
}
/// <summary>
- /// This is to be called just before the task does its final state transition.
+ /// This is to be called just before the task does its final state transition.
/// It traverses the list of exceptional children, and appends their aggregate exceptions into this one's exception list
/// </summary>
internal void AddExceptionsFromChildren(ContingentProperties props)
if (exceptionalChildren != null)
{
- // This lock is necessary because even though AddExceptionsFromChildren is last to execute, it may still
- // be racing with the code segment at the bottom of Finish() that prunes the exceptional child array.
+ // This lock is necessary because even though AddExceptionsFromChildren is last to execute, it may still
+ // be racing with the code segment at the bottom of Finish() that prunes the exceptional child array.
lock (exceptionalChildren)
{
foreach (Task task in exceptionalChildren)
/// <summary>
/// Performs whatever handling is necessary for an unhandled exception. Normally
- /// this just entails adding the exception to the holder object.
+ /// this just entails adding the exception to the holder object.
/// </summary>
/// <param name="unhandledException">The exception that went unhandled.</param>
private void HandleException(Exception unhandledException)
}
else
{
- // Other exceptions, including any OCE from the task that doesn't match the tasks' own CT,
- // or that gets thrown without the CT being set will be treated as an ordinary exception
+ // Other exceptions, including any OCE from the task that doesn't match the tasks' own CT,
+ // or that gets thrown without the CT being set will be treated as an ordinary exception
// and added to the aggregate.
AddException(unhandledException);
/// <summary>
/// Sets a continuation onto the <see cref="System.Threading.Tasks.Task"/>.
- /// The continuation is scheduled to run in the current synchronization context is one exists,
+ /// The continuation is scheduled to run in the current synchronization context is one exists,
/// otherwise in the current task scheduler.
/// </summary>
/// <param name="continuationAction">The action to invoke when the <see cref="System.Threading.Tasks.Task"/> has completed.</param>
Debug.Assert(continuationAction != null);
// Create the best AwaitTaskContinuation object given the request.
- // If this remains null by the end of the function, we can use the
+ // If this remains null by the end of the function, we can use the
// continuationAction directly without wrapping it.
TaskContinuation? tc = null;
if (continueOnCapturedContext)
{
// First try getting the current synchronization context.
- // If the current context is really just the base SynchronizationContext type,
- // which is intended to be equivalent to not having a current SynchronizationContext at all,
+ // If the current context is really just the base SynchronizationContext type,
+ // which is intended to be equivalent to not having a current SynchronizationContext at all,
// then ignore it. This helps with performance by avoiding unnecessary posts and queueing
- // of work items, but more so it ensures that if code happens to publish the default context
+ // of work items, but more so it ensures that if code happens to publish the default context
// as current, it won't prevent usage of a current task scheduler if there is one.
var syncCtx = SynchronizationContext.Current;
if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext))
/// <summary>
/// Sets a continuation onto the <see cref="System.Threading.Tasks.Task"/>.
- /// The continuation is scheduled to run in the current synchronization context is one exists,
+ /// The continuation is scheduled to run in the current synchronization context is one exists,
/// otherwise in the current task scheduler.
/// </summary>
/// <param name="stateMachineBox">The action to invoke when the <see cref="System.Threading.Tasks.Task"/> has completed.</param>
/// <summary>Creates an awaitable that asynchronously yields back to the current context when awaited.</summary>
/// <returns>
- /// A context that, when awaited, will asynchronously transition back into the current context at the
+ /// A context that, when awaited, will asynchronously transition back into the current context at the
/// time of the await. If the current SynchronizationContext is non-null, that is treated as the current context.
/// Otherwise, TaskScheduler.Current is treated as the current context.
/// </returns>
// Notify the debugger of the wait completion if it's requested such a notification
NotifyDebuggerOfWaitCompletionIfNecessary();
- // If cancellation was requested and the task was canceled, throw an
+ // If cancellation was requested and the task was canceled, throw an
// OperationCanceledException. This is prioritized ahead of the ThrowIfExceptional
- // call to bring more determinism to cases where the same token is used to
+ // call to bring more determinism to cases where the same token is used to
// cancel the Wait and to cancel the Task. Otherwise, there's a race condition between
// whether the Wait or the Task observes the cancellation request first,
// and different exceptions result from the different cases.
}
/// <summary>
- /// The core wait function, which is only accessible internally. It's meant to be used in places in TPL code where
+ /// The core wait function, which is only accessible internally. It's meant to be used in places in TPL code where
/// the current context is known or cached.
/// </summary>
[MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger
/// <summary>
/// Cancels the <see cref="Task"/>.
/// </summary>
- /// <param name="bCancelNonExecutingOnly">
+ /// <param name="bCancelNonExecutingOnly">
/// Indicates whether we should only cancel non-invoked tasks.
/// For the default scheduler this option will only be serviced through TryDequeue.
/// For custom schedulers we also attempt an atomic state transition.
}
catch (Exception e)
{
- // TryDequeue threw. We don't know whether the task was properly dequeued or not. So we must let the rest of
+ // TryDequeue threw. We don't know whether the task was properly dequeued or not. So we must let the rest of
// the cancellation logic run its course (record the request, attempt atomic state transition and do cleanup where appropriate)
// Here we will only record a TaskSchedulerException, which will later be thrown at function exit.
// Since that seems to have failed, we should now try an atomic state transition (from non-invoked state to canceled)
// An atomic transition here is only safe if we know we're on a custom task scheduler, which also forces a CAS on ExecuteEntry
- // Even though this task can't have any children, we should be ready for handling any continuations that
- // may be attached to it (although currently
+ // Even though this task can't have any children, we should be ready for handling any continuations that
+ // may be attached to it (although currently
// So we need to remeber whether we actually did the flip, so we can do clean up (finish continuations etc)
mustCleanup = AtomicStateUpdate(TASK_STATE_CANCELED, TASK_STATE_DELEGATE_INVOKED | TASK_STATE_CANCELED);
- // PS: This is slightly different from the regular cancellation codepath
- // since we record the cancellation request *after* doing the state transition.
+ // PS: This is slightly different from the regular cancellation codepath
+ // since we record the cancellation request *after* doing the state transition.
// However that shouldn't matter too much because the task was never invoked, thus can't have children
}
}
RecordInternalCancellationRequest();
// Determine whether we need to clean up
- // This will be the case
+ // This will be the case
// 1) if we were able to pop, and we are able to update task state to TASK_STATE_CANCELED
// 2) if the task seems to be yet unstarted, and we can transition to
- // TASK_STATE_CANCELED before anyone else can transition into _STARTED or _CANCELED or
+ // TASK_STATE_CANCELED before anyone else can transition into _STARTED or _CANCELED or
// _RAN_TO_COMPLETION or _FAULTED
// Note that we do not check for TASK_STATE_COMPLETION_RESERVED. That only applies to promise-style
// tasks, and a promise-style task should not enter into this codepath.
/// <summary>
/// Sets the task's cancellation acknowledged flag.
- /// </summary>
+ /// </summary>
private void SetCancellationAcknowledged()
{
Debug.Assert(this == Task.InternalCurrent, "SetCancellationAcknowledged() should only be called while this is still the current task");
bool returnValue = false;
// "Reserve" the completion for this task, while making sure that: (1) No prior reservation
- // has been made, (2) The result has not already been set, (3) An exception has not previously
+ // has been made, (2) The result has not already been set, (3) An exception has not previously
// been recorded, and (4) Cancellation has not been requested.
//
// If the reservation is successful, then add the exception(s) and finish completion processing.
bool returnValue = false;
// "Reserve" the completion for this task, while making sure that: (1) No prior reservation
- // has been made, (2) The result has not already been set, (3) An exception has not previously
+ // has been made, (2) The result has not already been set, (3) An exception has not previously
// been recorded, and (4) Cancellation has not been requested.
//
// If the reservation is successful, then record the cancellation and finish completion processing.
if (AsyncCausalityTracer.LoggingOn)
AsyncCausalityTracer.TraceSynchronousWorkStart(this, CausalitySynchronousWork.CompletionNotification);
- bool canInlineContinuations =
+ bool canInlineContinuations =
(m_stateFlags & (int)TaskCreationOptions.RunContinuationsAsynchronously) == 0 &&
RuntimeHelpers.TryEnsureSufficientExecutionStack();
// Create a TaskContinuation
TaskContinuation continuation = new StandardTaskContinuation(continuationTask, options, scheduler);
- // If cancellationToken is cancellable, then assign it.
+ // If cancellationToken is cancellable, then assign it.
if (cancellationToken.CanBeCanceled)
{
if (IsCompleted || cancellationToken.IsCancellationRequested)
// the motions of queuing up the continuation for eventual execution.
if (!continuationTask.IsCompleted)
{
- // We need additional correlation produced here to ensure that at least the continuation
+ // We need additional correlation produced here to ensure that at least the continuation
// code will be correlatable to the currrent activity that initiated "this" task:
- // . when the antecendent ("this") is a promise we have very little control over where
- // the code for the promise will run (e.g. it can be a task from a user provided
- // TaskCompletionSource or from a classic Begin/End async operation); this user or
+ // . when the antecendent ("this") is a promise we have very little control over where
+ // the code for the promise will run (e.g. it can be a task from a user provided
+ // TaskCompletionSource or from a classic Begin/End async operation); this user or
// system code will likely not have stamped an activity id on the thread, so there's
// generally no easy correlation that can be provided between the current activity
- // and the promise. Also the continuation code may run practically on any thread.
+ // and the promise. Also the continuation code may run practically on any thread.
// Since there may be no correlation between the current activity and the TCS's task
// activity, we ensure we at least create a correlation from the current activity to
// the continuation that runs when the promise completes.
}
// We need to prevent the tasks array from being GC'ed until we come out of the wait.
- // This is necessary so that the Parallel Debugger can traverse it during the long wait and
+ // This is necessary so that the Parallel Debugger can traverse it during the long wait and
// deduce waiter/waitee relationships
GC.KeepAlive(tasks);
}
- // Now that we're done and about to exit, if the wait completed and if we have
+ // Now that we're done and about to exit, if the wait completed and if we have
// any tasks with a notification bit set, signal the debugger if any requires it.
if (returnValue && notificationTasks != null)
{
// If one or more threw exceptions, aggregate and throw them.
if (returnValue && (exceptionSeen || cancellationSeen))
{
- // If the WaitAll was canceled and tasks were canceled but not faulted,
- // prioritize throwing an OCE for canceling the WaitAll over throwing an
+ // If the WaitAll was canceled and tasks were canceled but not faulted,
+ // prioritize throwing an OCE for canceling the WaitAll over throwing an
// AggregateException for all of the canceled Tasks. This helps
// to bring determinism to an otherwise non-determistic case of using
// the same token to cancel both the WaitAll and the Tasks.
}
// We need to prevent the tasks array from being GC'ed until we come out of the wait.
- // This is necessary so that the Parallel Debugger can traverse it during the long wait
+ // This is necessary so that the Parallel Debugger can traverse it during the long wait
// and deduce waiter/waitee relationships
GC.KeepAlive(tasks);
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">
/// The provided <paramref name="cancellationToken"/> has already been disposed.
- /// </exception>
+ /// </exception>
/// <remarks>
/// If the cancellation token is signaled before the specified time delay, then the Task is completed in
/// Canceled state. Otherwise, the Task is completed in RanToCompletion state once the specified time
/// delay has expired.
- /// </remarks>
+ /// </remarks>
public static Task Delay(TimeSpan delay, CancellationToken cancellationToken)
{
long totalMilliseconds = (long)delay.TotalMilliseconds;
/// </exception>
/// <exception cref="T:System.ObjectDisposedException">
/// The provided <paramref name="cancellationToken"/> has already been disposed.
- /// </exception>
+ /// </exception>
/// <remarks>
/// If the cancellation token is signaled before the specified time delay, then the Task is completed in
/// Canceled state. Otherwise, the Task is completed in RanToCompletion state once the specified time
/// delay has expired.
- /// </remarks>
+ /// </remarks>
public static Task Delay(int millisecondsDelay, CancellationToken cancellationToken)
{
// Throw on non-sensical time
/// <returns>A task that represents the completion of all of the supplied tasks.</returns>
/// <remarks>
/// <para>
- /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state,
- /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.
+ /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state,
+ /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.
/// </para>
/// <para>
/// If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state.
/// </para>
/// <para>
- /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.
+ /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.
/// </para>
/// <para>
- /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion
- /// state before it's returned to the caller.
+ /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion
+ /// state before it's returned to the caller.
/// </para>
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// <returns>A task that represents the completion of all of the supplied tasks.</returns>
/// <remarks>
/// <para>
- /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state,
- /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.
+ /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state,
+ /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.
/// </para>
/// <para>
/// If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state.
/// </para>
/// <para>
- /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.
+ /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.
/// </para>
/// <para>
- /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion
- /// state before it's returned to the caller.
+ /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion
+ /// state before it's returned to the caller.
/// </para>
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
public bool InvokeMayRunArbitraryCode { get { return true; } }
/// <summary>
- /// Returns whether we should notify the debugger of a wait completion. This returns
+ /// Returns whether we should notify the debugger of a wait completion. This returns
/// true iff at least one constituent task has its bit set.
/// </summary>
internal override bool ShouldNotifyDebuggerOfWaitCompletion
/// <returns>A task that represents the completion of all of the supplied tasks.</returns>
/// <remarks>
/// <para>
- /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state,
- /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.
+ /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state,
+ /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.
/// </para>
/// <para>
/// If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state.
/// </para>
/// <para>
- /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.
- /// The Result of the returned task will be set to an array containing all of the results of the
- /// supplied tasks in the same order as they were provided (e.g. if the input tasks array contained t1, t2, t3, the output
- /// task's Result will return an TResult[] where arr[0] == t1.Result, arr[1] == t2.Result, and arr[2] == t3.Result).
+ /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.
+ /// The Result of the returned task will be set to an array containing all of the results of the
+ /// supplied tasks in the same order as they were provided (e.g. if the input tasks array contained t1, t2, t3, the output
+ /// task's Result will return an TResult[] where arr[0] == t1.Result, arr[1] == t2.Result, and arr[2] == t3.Result).
/// </para>
/// <para>
- /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion
+ /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion
/// state before it's returned to the caller. The returned TResult[] will be an array of 0 elements.
/// </para>
/// </remarks>
/// </exception>
/// <exception cref="T:System.ArgumentException">
/// The <paramref name="tasks"/> collection contained a null task.
- /// </exception>
+ /// </exception>
public static Task<TResult[]> WhenAll<TResult>(IEnumerable<Task<TResult>> tasks)
{
// Take a more efficient route if tasks is actually an array
/// <returns>A task that represents the completion of all of the supplied tasks.</returns>
/// <remarks>
/// <para>
- /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state,
- /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.
+ /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state,
+ /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.
/// </para>
/// <para>
/// If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state.
/// </para>
/// <para>
- /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.
- /// The Result of the returned task will be set to an array containing all of the results of the
- /// supplied tasks in the same order as they were provided (e.g. if the input tasks array contained t1, t2, t3, the output
- /// task's Result will return an TResult[] where arr[0] == t1.Result, arr[1] == t2.Result, and arr[2] == t3.Result).
+ /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.
+ /// The Result of the returned task will be set to an array containing all of the results of the
+ /// supplied tasks in the same order as they were provided (e.g. if the input tasks array contained t1, t2, t3, the output
+ /// task's Result will return an TResult[] where arr[0] == t1.Result, arr[1] == t2.Result, and arr[2] == t3.Result).
/// </para>
/// <para>
- /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion
+ /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion
/// state before it's returned to the caller. The returned TResult[] will be an array of 0 elements.
/// </para>
/// </remarks>
/// <param name="tasks">The tasks to wait on for completion.</param>
/// <returns>A task that represents the completion of one of the supplied tasks. The return Task's Result is the task that completed.</returns>
/// <remarks>
- /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state
+ /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state
/// with its Result set to the first task to complete. This is true even if the first task to complete ended in the Canceled or Faulted state.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// <param name="tasks">The tasks to wait on for completion.</param>
/// <returns>A task that represents the completion of one of the supplied tasks. The return Task's Result is the task that completed.</returns>
/// <remarks>
- /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state
+ /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state
/// with its Result set to the first task to complete. This is true even if the first task to complete ended in the Canceled or Faulted state.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// <param name="tasks">The tasks to wait on for completion.</param>
/// <returns>A task that represents the completion of one of the supplied tasks. The return Task's Result is the task that completed.</returns>
/// <remarks>
- /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state
+ /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state
/// with its Result set to the first task to complete. This is true even if the first task to complete ended in the Canceled or Faulted state.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// <param name="tasks">The tasks to wait on for completion.</param>
/// <returns>A task that represents the completion of one of the supplied tasks. The return Task's Result is the task that completed.</returns>
/// <remarks>
- /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state
+ /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state
/// with its Result set to the first task to complete. This is true even if the first task to complete ended in the Canceled or Faulted state.
/// </remarks>
/// <exception cref="T:System.ArgumentNullException">
/// <summary>
/// Specifies that a task will be a long-running, course-grained operation. It provides a hint to the
/// <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> that oversubscription may be
- /// warranted.
+ /// warranted.
/// </summary>
LongRunning = 0x02,
/// </summary>
LazyCancellation = 0x1000,
- /// <summary>Specifies that the task will be queued by the runtime before handing it over to the user.
+ /// <summary>Specifies that the task will be queued by the runtime before handing it over to the user.
/// This flag will be used to skip the cancellationtoken registration step, which is only meant for unstarted tasks.</summary>
QueuedByRuntime = 0x2000,
}
}
- // For ITaskCompletionAction
+ // For ITaskCompletionAction
public void Invoke(Task completingTask)
{
// If we're ok to inline, process the task. Otherwise, we're too deep on the stack, and
switch (task.Status)
{
- // If the outer task did not complete successfully, then record the
+ // If the outer task did not complete successfully, then record the
// cancellation/fault information to tcs.Task.
case TaskStatus.Canceled:
case TaskStatus.Faulted:
}
/// <summary>
- /// Processes the inner task of a Task{Task} or Task{Task{TResult}},
+ /// Processes the inner task of a Task{Task} or Task{Task{TResult}},
/// transferring the appropriate results to ourself.
/// </summary>
/// <param name="task">The inner task returned by the task provided by the user.</param>
/// Gets the task associated with this exception.
/// </summary>
/// <remarks>
- /// It is permissible for no Task to be associated with a
+ /// It is permissible for no Task to be associated with a
/// <see cref="T:System.Threading.Tasks.TaskCanceledException"/>, in which case
/// this property will return null.
/// </remarks>
/// Creates a <see cref="TaskCompletionSource{TResult}"/>
/// with the specified state.
/// </summary>
- /// <param name="state">The state to use as the underlying
+ /// <param name="state">The state to use as the underlying
/// <see cref="T:System.Threading.Tasks.Task{TResult}"/>'s AsyncState.</param>
public TaskCompletionSource(object? state)
: this(state, TaskCreationOptions.None)
/// </summary>
/// <param name="creationOptions">The options to use when creating the underlying
/// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
- /// <param name="state">The state to use as the underlying
+ /// <param name="state">The state to use as the underlying
/// <see cref="T:System.Threading.Tasks.Task{TResult}"/>'s AsyncState.</param>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// The <paramref name="creationOptions"/> represent options invalid for use
/// <summary>
/// Attempts to transition the underlying
- /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
/// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>
/// state.
/// </summary>
- /// <param name="exception">The exception to bind to this <see
+ /// <param name="exception">The exception to bind to this <see
/// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
/// <returns>True if the operation was successful; otherwise, false.</returns>
- /// <remarks>This operation will return false if the
+ /// <remarks>This operation will return false if the
/// <see cref="T:System.Threading.Tasks.Task{TResult}"/> is already in one
/// of the three final states:
- /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
/// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
/// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
/// </remarks>
/// <summary>
/// Attempts to transition the underlying
- /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
/// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>
/// state.
/// </summary>
- /// <param name="exceptions">The collection of exceptions to bind to this <see
+ /// <param name="exceptions">The collection of exceptions to bind to this <see
/// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
/// <returns>True if the operation was successful; otherwise, false.</returns>
- /// <remarks>This operation will return false if the
+ /// <remarks>This operation will return false if the
/// <see cref="T:System.Threading.Tasks.Task{TResult}"/> is already in one
/// of the three final states:
- /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
/// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
/// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
/// </remarks>
/// <summary>
/// Transitions the underlying
- /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
/// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>
/// state.
/// </summary>
- /// <param name="exception">The exception to bind to this <see
+ /// <param name="exception">The exception to bind to this <see
/// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="exception"/> argument is null.</exception>
/// <exception cref="T:System.InvalidOperationException">
/// The underlying <see cref="T:System.Threading.Tasks.Task{TResult}"/> is already in one
/// of the three final states:
- /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
/// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
/// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
/// </exception>
/// <summary>
/// Transitions the underlying
- /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
/// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>
/// state.
/// </summary>
- /// <param name="exceptions">The collection of exceptions to bind to this <see
+ /// <param name="exceptions">The collection of exceptions to bind to this <see
/// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="exceptions"/> argument is null.</exception>
/// <exception cref="T:System.ArgumentException">There are one or more null elements in <paramref name="exceptions"/>.</exception>
/// <exception cref="T:System.InvalidOperationException">
/// The underlying <see cref="T:System.Threading.Tasks.Task{TResult}"/> is already in one
/// of the three final states:
- /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
/// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
/// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
/// </exception>
/// <summary>
/// Attempts to transition the underlying
- /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
/// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>
/// state.
/// </summary>
- /// <param name="result">The result value to bind to this <see
+ /// <param name="result">The result value to bind to this <see
/// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
/// <returns>True if the operation was successful; otherwise, false.</returns>
- /// <remarks>This operation will return false if the
+ /// <remarks>This operation will return false if the
/// <see cref="T:System.Threading.Tasks.Task{TResult}"/> is already in one
/// of the three final states:
- /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
/// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
/// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
/// </remarks>
/// <summary>
/// Transitions the underlying
- /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
/// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>
/// state.
/// </summary>
- /// <param name="result">The result value to bind to this <see
+ /// <param name="result">The result value to bind to this <see
/// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
/// <exception cref="T:System.InvalidOperationException">
/// The underlying <see cref="T:System.Threading.Tasks.Task{TResult}"/> is already in one
/// of the three final states:
- /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
/// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
/// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
/// </exception>
/// <summary>
/// Attempts to transition the underlying
- /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
/// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>
/// state.
/// </summary>
/// <returns>True if the operation was successful; otherwise, false.</returns>
- /// <remarks>This operation will return false if the
+ /// <remarks>This operation will return false if the
/// <see cref="T:System.Threading.Tasks.Task{TResult}"/> is already in one
/// of the three final states:
- /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
/// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
/// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
/// </remarks>
/// <summary>
/// Transitions the underlying
- /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
/// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>
/// state.
/// </summary>
/// <exception cref="T:System.InvalidOperationException">
/// The underlying <see cref="T:System.Threading.Tasks.Task{TResult}"/> is already in one
/// of the three final states:
- /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
/// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
/// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
/// </exception>
/// <summary>
/// Evaluates the value selector of the Task which is passed in as an object and stores the result.
- /// </summary>
+ /// </summary>
internal override void InnerInvoke()
{
// Get and null out the antecedent. This is crucial to avoid a memory
/// <summary>
/// Evaluates the value selector of the Task which is passed in as an object and stores the result.
- /// </summary>
+ /// </summary>
internal override void InnerInvoke()
{
// Get and null out the antecedent. This is crucial to avoid a memory
catch (Exception e)
{
// Either TryRunInline() or QueueTask() threw an exception. Record the exception, marking the task as Faulted.
- // However if it was a ThreadAbortException coming from TryRunInline we need to skip here,
+ // However if it was a ThreadAbortException coming from TryRunInline we need to skip here,
// because it would already have been handled in Task.Execute()
TaskSchedulerException tse = new TaskSchedulerException(e);
task.AddException(tse);
Debug.Assert(completedTask != null);
Debug.Assert(completedTask.IsCompleted, "ContinuationTask.Run(): completedTask not completed");
- // Check if the completion status of the task works with the desired
+ // Check if the completion status of the task works with the desired
// activation criteria of the TaskContinuationOptions.
TaskContinuationOptions options = m_options;
bool isRightKind =
try { continuationTask.ScheduleAndStart(needsProtection: true); }
catch (TaskSchedulerException)
{
- // No further action is necessary -- ScheduleAndStart() already transitioned the
+ // No further action is necessary -- ScheduleAndStart() already transitioned the
// task to faulted. But we want to make sure that no exception is thrown from here.
}
}
/// <summary>Gets a cached delegate for the PostAction method.</summary>
/// <returns>
- /// A delegate for PostAction, which expects a SynchronizationContextAwaitTaskContinuation
+ /// A delegate for PostAction, which expects a SynchronizationContextAwaitTaskContinuation
/// to be passed as state.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
}
else
{
- // We permit inlining if the caller allows us to, and
+ // We permit inlining if the caller allows us to, and
// either we're on a thread pool thread (in which case we're fine running arbitrary code)
// or we're already on the target scheduler (in which case we'll just ask the scheduler
// whether it's ok to run here). We include the IsThreadPoolThread check here, whereas
bool inlineIfPossible = canInlineContinuationTask &&
(TaskScheduler.InternalCurrent == m_scheduler || Thread.CurrentThread.IsThreadPoolThread);
- // Create the continuation task task. If we're allowed to inline, try to do so.
+ // Create the continuation task task. If we're allowed to inline, try to do so.
// The target scheduler may still deny us from executing on this thread, in which case this'll be queued.
var task = CreateTask(state =>
{
internal override void Run(Task task, bool canInlineContinuationTask)
{
// For the base AwaitTaskContinuation, we allow inlining if our caller allows it
- // and if we're in a "valid location" for it. See the comments on
+ // and if we're in a "valid location" for it. See the comments on
// IsValidLocationForInlining for more about what's valid. For performance
// reasons we would like to always inline, but we don't in some cases to avoid
// running arbitrary amounts of work in suspected "bad locations", like UI threads.
/// </summary>
/// <remarks>
/// Returns whether SynchronizationContext is null and we're in the default scheduler.
- /// If the await had a SynchronizationContext/TaskScheduler where it began and the
- /// default/ConfigureAwait(true) was used, then we won't be on this path. If, however,
- /// ConfigureAwait(false) was used, or the SynchronizationContext and TaskScheduler were
+ /// If the await had a SynchronizationContext/TaskScheduler where it began and the
+ /// default/ConfigureAwait(true) was used, then we won't be on this path. If, however,
+ /// ConfigureAwait(false) was used, or the SynchronizationContext and TaskScheduler were
/// naturally null/Default, then we might end up here. If we do, we need to make sure
/// that we don't execute continuations in a place that isn't set up to handle them, e.g.
/// running arbitrary amounts of code on the UI thread. It would be "correct", but very
{
get
{
- // If there's a SynchronizationContext, we'll be conservative and say
+ // If there's a SynchronizationContext, we'll be conservative and say
// this is a bad location to inline.
var ctx = SynchronizationContext.Current;
if (ctx != null && ctx.GetType() != typeof(SynchronizationContext)) return false;
/// An exception holder manages a list of exceptions for one particular task.
/// It offers the ability to aggregate, but more importantly, also offers intrinsic
/// support for propagating unhandled exceptions that are never observed. It does
- /// this by aggregating and calling UnobservedTaskException event event if the holder
- /// is ever GC'd without the holder's contents ever having been requested
+ /// this by aggregating and calling UnobservedTaskException event event if the holder
+ /// is ever GC'd without the holder's contents ever having been requested
/// (e.g. by a Task.Wait, Task.get_Exception, etc).
/// </summary>
internal class TaskExceptionHolder
/// </param>
/// <param name="exceptionObject">
/// An exception object (either an Exception, an ExceptionDispatchInfo,
- /// an IEnumerable{Exception}, or an IEnumerable{ExceptionDispatchInfo})
+ /// an IEnumerable{Exception}, or an IEnumerable{ExceptionDispatchInfo})
/// to add to the list.
/// </param>
/// <remarks>
/// A private helper method that ensures the holder is considered
/// handled, i.e. it is not registered for finalization.
/// </summary>
- /// <param name="calledFromFinalizer">Whether this is called from the finalizer thread.</param>
+ /// <param name="calledFromFinalizer">Whether this is called from the finalizer thread.</param>
internal void MarkAsHandled(bool calledFromFinalizer)
{
if (!m_isHandled)
// Mark as handled and aggregate the exceptions.
MarkAsHandled(calledFromFinalizer);
- // If we're only including the previously captured exceptions,
+ // If we're only including the previously captured exceptions,
// return them immediately in an aggregate.
if (includeThisException == null)
return new AggregateException(exceptions);
- // Otherwise, the caller wants a specific exception to be included,
+ // Otherwise, the caller wants a specific exception to be included,
// so return an aggregate containing that exception and the rest.
Exception[] combinedExceptions = new Exception[exceptions.Count + 1];
for (int i = 0; i < combinedExceptions.Length - 1; i++)
}
/// <summary>
- /// Wraps the exception dispatch infos into a new read-only collection. By calling this method,
- /// the holder assumes exceptions to have been "observed", such that the finalization
+ /// Wraps the exception dispatch infos into a new read-only collection. By calling this method,
+ /// the holder assumes exceptions to have been "observed", such that the finalization
/// check will be subsequently skipped.
/// </summary>
internal ReadOnlyCollection<ExceptionDispatchInfo> GetExceptionDispatchInfos()
}
/// <summary>
- /// Gets the ExceptionDispatchInfo representing the singular exception
+ /// Gets the ExceptionDispatchInfo representing the singular exception
/// that was the cause of the task's cancellation.
/// </summary>
/// <returns>
//
//
//
-// There are a plethora of common patterns for which Tasks are created. TaskFactory encodes
-// these patterns into helper methods. These helpers also pick up default configuration settings
+// There are a plethora of common patterns for which Tasks are created. TaskFactory encodes
+// these patterns into helper methods. These helpers also pick up default configuration settings
// applicable to the entire factory and configurable through its constructors.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
/// <summary>
/// Initializes a <see cref="TaskFactory"/> instance with the specified configuration.
/// </summary>
- /// <param name="cancellationToken">The default <see cref="CancellationToken"/> that will be assigned
- /// to tasks created by this <see cref="TaskFactory"/> unless another CancellationToken is explicitly specified
+ /// <param name="cancellationToken">The default <see cref="CancellationToken"/> that will be assigned
+ /// to tasks created by this <see cref="TaskFactory"/> unless another CancellationToken is explicitly specified
/// while calling the factory methods.</param>
/// <remarks>
/// This constructor creates a <see cref="TaskFactory"/> instance with a default configuration. The
/// <summary>
/// Initializes a <see cref="TaskFactory"/> instance with the specified configuration.
/// </summary>
- /// <param name="cancellationToken">The default <see cref="CancellationToken"/> that will be assigned
- /// to tasks created by this <see cref="TaskFactory"/> unless another CancellationToken is explicitly specified
+ /// <param name="cancellationToken">The default <see cref="CancellationToken"/> that will be assigned
+ /// to tasks created by this <see cref="TaskFactory"/> unless another CancellationToken is explicitly specified
/// while calling the factory methods.</param>
/// <param name="creationOptions">
/// The default <see cref="System.Threading.Tasks.TaskCreationOptions">
/// TaskFactory.
/// </summary>
/// <remarks>
- /// This property returns the default <see cref="CancellationToken"/> that will be assigned to all
- /// tasks created by this factory unless another CancellationToken value is explicitly specified
+ /// This property returns the default <see cref="CancellationToken"/> that will be assigned to all
+ /// tasks created by this factory unless another CancellationToken value is explicitly specified
/// during the call to the factory methods.
/// </remarks>
public CancellationToken CancellationToken { get { return m_defaultCancellationToken; } }
/// TaskFactory.
/// </summary>
/// <remarks>
- /// This property returns the default scheduler for this factory. It will be used to schedule all
- /// tasks unless another scheduler is explicitly specified during calls to this factory's methods.
- /// If null, <see cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>
+ /// This property returns the default scheduler for this factory. It will be used to schedule all
+ /// tasks unless another scheduler is explicitly specified during calls to this factory's methods.
+ /// If null, <see cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>
/// will be used.
/// </remarks>
public TaskScheduler? Scheduler { get { return m_defaultScheduler; } }
/// </see> value of this TaskFactory.
/// </summary>
/// <remarks>
- /// This property returns the default creation options for this factory. They will be used to create all
+ /// This property returns the default creation options for this factory. They will be used to create all
/// tasks unless other options are explicitly specified during calls to this factory's methods.
/// </remarks>
public TaskCreationOptions CreationOptions { get { return m_defaultCreationOptions; } }
/// </see> value of this TaskFactory.
/// </summary>
/// <remarks>
- /// This property returns the default continuation options for this factory. They will be used to create
+ /// This property returns the default continuation options for this factory. They will be used to create
/// all continuation tasks unless other options are explicitly specified during calls to this factory's methods.
/// </remarks>
public TaskContinuationOptions ContinuationOptions { get { return m_defaultContinuationOptions; } }
/// </summary>
/// <param name="action">The action delegate to execute asynchronously.</param>
/// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="action"/>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="action"/>
/// argument is null.</exception>
/// <remarks>
- /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors
- /// and then calling
+ /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors
+ /// and then calling
/// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. However,
/// unless creation and scheduling must be separated, StartNew is the recommended
/// approach for both simplicity and performance.
/// <param name="action">The action delegate to execute asynchronously.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
/// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="action"/>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="action"/>
/// argument is null.</exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
/// <remarks>
- /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors
- /// and then calling
+ /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors
+ /// and then calling
/// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. However,
/// unless creation and scheduling must be separated, StartNew is the recommended
/// approach for both simplicity and performance.
public bool InvokeMayRunArbitraryCode { get { return true; } }
/// <summary>
- /// Returns whether we should notify the debugger of a wait completion. This returns
+ /// Returns whether we should notify the debugger of a wait completion. This returns
/// true iff at least one constituent task has its bit set.
/// </summary>
internal override bool ShouldNotifyDebuggerOfWaitCompletion
public bool InvokeMayRunArbitraryCode { get { return true; } }
/// <summary>
- /// Returns whether we should notify the debugger of a wait completion. This returns
+ /// Returns whether we should notify the debugger of a wait completion. This returns
/// true iff at least one constituent task has its bit set.
/// </summary>
internal override bool ShouldNotifyDebuggerOfWaitCompletion
return promise;
}
/// <summary>
- /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
/// that will be started upon the completion of a set of provided Tasks.
/// </summary>
/// <param name="tasks">The array of tasks from which to continue.</param>
- /// <param name="continuationAction">The action delegate to execute when all tasks in
+ /// <param name="continuationAction">The action delegate to execute when all tasks in
/// the <paramref name="tasks"/> array have completed.</param>
/// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="tasks"/> array is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="continuationAction"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array contains a null value.</exception>
- /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
public Task ContinueWhenAll(Task[] tasks, Action<Task[]> continuationAction)
{
/// <summary>
- /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
/// that will be started upon the completion of a set of provided Tasks.
/// </summary>
/// <param name="tasks">The array of tasks from which to continue.</param>
- /// <param name="continuationAction">The action delegate to execute when all tasks in
+ /// <param name="continuationAction">The action delegate to execute when all tasks in
/// the <paramref name="tasks"/> array have completed.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="tasks"/> array is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="continuationAction"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array contains a null value.</exception>
- /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
/// value.</exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
public Task ContinueWhenAll(Task[] tasks, Action<Task[]> continuationAction, TaskContinuationOptions continuationOptions)
/// <param name="tasks">The array of tasks from which to continue.</param>
/// <param name="continuationAction">The action delegate to execute when all tasks in the <paramref
/// name="tasks"/> array have completed.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
/// TaskContinuationOptions</see> value that controls the behavior of
/// has already been disposed.
/// </exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
public Task ContinueWhenAll(Task[] tasks, Action<Task[]> continuationAction, CancellationToken cancellationToken,
}
/// <summary>
- /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
/// that will be started upon the completion of a set of provided Tasks.
/// </summary>
/// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
/// <param name="tasks">The array of tasks from which to continue.</param>
- /// <param name="continuationAction">The action delegate to execute when all tasks in
+ /// <param name="continuationAction">The action delegate to execute when all tasks in
/// the <paramref name="tasks"/> array have completed.</param>
/// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="tasks"/> array is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="continuationAction"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array contains a null value.</exception>
- /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
public Task ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationAction)
{
/// <summary>
- /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
/// that will be started upon the completion of a set of provided Tasks.
/// </summary>
/// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
/// <param name="tasks">The array of tasks from which to continue.</param>
- /// <param name="continuationAction">The action delegate to execute when all tasks in
+ /// <param name="continuationAction">The action delegate to execute when all tasks in
/// the <paramref name="tasks"/> array have completed.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="tasks"/> array is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="continuationAction"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array contains a null value.</exception>
- /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
/// value.</exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
public Task ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationAction,
/// <param name="tasks">The array of tasks from which to continue.</param>
/// <param name="continuationAction">The action delegate to execute when all tasks in the <paramref
/// name="tasks"/> array have completed.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
/// TaskContinuationOptions</see> value that controls the behavior of
/// has already been disposed.
/// </exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
public Task ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationAction,
/// <param name="tasks">The array of tasks from which to continue.</param>
/// <param name="continuationFunction">The function delegate to execute when all tasks in the
/// <paramref name="tasks"/> array have completed.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
/// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
/// value.</exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
public Task<TResult> ContinueWhenAll<TResult>(Task[] tasks, Func<Task[], TResult> continuationFunction, TaskContinuationOptions continuationOptions)
/// <param name="tasks">The array of tasks from which to continue.</param>
/// <param name="continuationFunction">The function delegate to execute when all tasks in the
/// <paramref name="tasks"/> array have completed.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
/// TaskContinuationOptions</see> value that controls the behavior of
/// has already been disposed.
/// </exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
public Task<TResult> ContinueWhenAll<TResult>(Task[] tasks, Func<Task[], TResult> continuationFunction, CancellationToken cancellationToken,
/// <param name="tasks">The array of tasks from which to continue.</param>
/// <param name="continuationFunction">The function delegate to execute when all tasks in the
/// <paramref name="tasks"/> array have completed.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
/// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
/// value.</exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
/// <param name="tasks">The array of tasks from which to continue.</param>
/// <param name="continuationFunction">The function delegate to execute when all tasks in the
/// <paramref name="tasks"/> array have completed.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
/// TaskContinuationOptions</see> value that controls the behavior of
/// has already been disposed.
/// </exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
public bool InvokeMayRunArbitraryCode => (_stateFlags & SyncBlockingFlag) == 0;
}
// Common ContinueWhenAny logic
- // If the tasks list is not an array, it must be an internal defensive copy so that
+ // If the tasks list is not an array, it must be an internal defensive copy so that
// we don't need to be concerned about concurrent modifications to the list. If the task list
// is an array, it should be a defensive copy if this functionality is being used
// asynchronously (e.g. WhenAny) rather than synchronously (e.g. WaitAny).
/// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
/// <param name="continuationAction">The action delegate to execute when one task in the <paramref
/// name="tasks"/> array completes.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
/// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
/// value.</exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
public Task ContinueWhenAny(Task[] tasks, Action<Task> continuationAction, TaskContinuationOptions continuationOptions)
/// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
/// <param name="continuationAction">The action delegate to execute when one task in the <paramref
/// name="tasks"/> array completes.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
/// TaskContinuationOptions</see> value that controls the behavior of
/// has already been disposed.
/// </exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
public Task ContinueWhenAny(Task[] tasks, Action<Task> continuationAction, CancellationToken cancellationToken,
/// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
/// <param name="continuationFunction">The function delegate to execute when one task in the
/// <paramref name="tasks"/> array completes.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
/// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
/// value.</exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
public Task<TResult> ContinueWhenAny<TResult>(Task[] tasks, Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions)
/// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
/// <param name="continuationFunction">The function delegate to execute when one task in the
/// <paramref name="tasks"/> array completes.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
/// TaskContinuationOptions</see> value that controls the behavior of
/// has already been disposed.
/// </exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
public Task<TResult> ContinueWhenAny<TResult>(Task[] tasks, Func<Task, TResult> continuationFunction, CancellationToken cancellationToken,
/// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
/// <param name="continuationFunction">The function delegate to execute when one task in the
/// <paramref name="tasks"/> array completes.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
/// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
/// value.</exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
/// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
/// <param name="continuationFunction">The function delegate to execute when one task in the
/// <paramref name="tasks"/> array completes.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
/// TaskContinuationOptions</see> value that controls the behavior of
/// has already been disposed.
/// </exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
/// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
/// <param name="continuationAction">The action delegate to execute when one task in the
/// <paramref name="tasks"/> array completes.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task"/>.</returns>
/// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
/// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
/// value.</exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
public Task ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction,
/// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
/// <param name="continuationAction">The action delegate to execute when one task in the
/// <paramref name="tasks"/> array completes.</param>
- /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// that will be assigned to the new continuation task.</param>
/// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
/// TaskContinuationOptions</see> value that controls the behavior of
/// has already been disposed.
/// </exception>
/// <remarks>
- /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
- /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
public Task ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction,
-// Licensed to the .NET Foundation under one or more agreements.
+// 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.
//
//
//
-// This file contains the primary interface and management of tasks and queues.
+// This file contains the primary interface and management of tasks and queues.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
/// </summary>
/// <remarks>
/// <para>
- /// <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> acts as the extension point for all
+ /// <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> acts as the extension point for all
/// pluggable scheduling logic. This includes mechanisms such as how to schedule a task for execution, and
/// how scheduled tasks should be exposed to debuggers.
/// </para>
/// </summary>
/// <remarks>
/// <para>
- /// A class derived from <see cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// A class derived from <see cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
/// implements this method to accept tasks being scheduled on the scheduler.
/// A typical implementation would store the task in an internal data structure, which would
/// be serviced by threads that would execute those tasks at some time in the future.
/// </para>
/// <para>
/// This method is only meant to be called by the .NET Framework and
- /// should not be called directly by the derived class. This is necessary
+ /// should not be called directly by the derived class. This is necessary
/// for maintaining the consistency of the system.
/// </para>
/// </remarks>
protected abstract IEnumerable<Task>? GetScheduledTasks();
/// <summary>
- /// Indicates the maximum concurrency level this
+ /// Indicates the maximum concurrency level this
/// <see cref="TaskScheduler"/> is able to support.
/// </summary>
public virtual int MaximumConcurrencyLevel
return false;
}
- // Task class will still call into TaskScheduler.TryRunInline rather than TryExecuteTaskInline() so that
+ // Task class will still call into TaskScheduler.TryRunInline rather than TryExecuteTaskInline() so that
// 1) we can adjust the return code from TryExecuteTaskInline in case a buggy custom scheduler lies to us
// 2) we maintain a mechanism for the TLS lookup optimization that we used to have for the ConcRT scheduler (will potentially introduce the same for TP)
if (TplEventSource.Log.IsEnabled())
protected TaskScheduler()
{
#if CORECLR // Debugger support
- // Register the scheduler in the active scheduler list. This is only relevant when debugging,
+ // Register the scheduler in the active scheduler list. This is only relevant when debugging,
// so we only pay the cost if the debugger is attached when the scheduler is created. This
// means that the internal TaskScheduler.GetTaskSchedulersForDebugger() will only include
// schedulers created while the debugger is attached.
/// associated with the current <see cref="T:System.Threading.SynchronizationContext"/>.
/// </summary>
/// <remarks>
- /// All <see cref="System.Threading.Tasks.Task">Task</see> instances queued to
+ /// All <see cref="System.Threading.Tasks.Task">Task</see> instances queued to
/// the returned scheduler will be executed through a call to the
/// <see cref="System.Threading.SynchronizationContext.Post">Post</see> method
/// on that context.
/// </remarks>
/// <returns>
- /// A <see cref="TaskScheduler"/> associated with
+ /// A <see cref="TaskScheduler"/> associated with
/// the current <see cref="T:System.Threading.SynchronizationContext">SynchronizationContext</see>, as
/// determined by <see cref="System.Threading.SynchronizationContext.Current">SynchronizationContext.Current</see>.
/// </returns>
/// </summary>
/// <remarks>
/// This AppDomain-wide event provides a mechanism to prevent exception
- /// escalation policy (which, by default, terminates the process) from triggering.
+ /// escalation policy (which, by default, terminates the process) from triggering.
/// Each handler is passed a <see cref="T:System.Threading.Tasks.UnobservedTaskExceptionEventArgs"/>
/// instance, which may be used to examine the exception and to mark it as observed.
/// </remarks>
/// </summary>
/// <remarks>
/// The returned array is populated through a call to <see cref="GetScheduledTasks"/>.
- /// Note that this function is only meant to be invoked by a debugger remotely.
+ /// Note that this function is only meant to be invoked by a debugger remotely.
/// It should not be called by any other codepaths.
/// </remarks>
- /// <returns>An array of <see cref="System.Threading.Tasks.Task">Task</see> instances.</returns>
+ /// <returns>An array of <see cref="System.Threading.Tasks.Task">Task</see> instances.</returns>
/// <exception cref="T:System.NotSupportedException">
/// This scheduler is unable to generate a list of queued tasks at this time.
/// </exception>
}
/// <summary>
- /// Provides an array of all active <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// Provides an array of all active <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
/// instances for the debugger.
/// </summary>
/// <remarks>
- /// This function is only meant to be invoked by a debugger remotely.
+ /// This function is only meant to be invoked by a debugger remotely.
/// It should not be called by any other codepaths.
/// </remarks>
- /// <returns>An array of <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> instances.</returns>
+ /// <returns>An array of <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> instances.</returns>
internal static TaskScheduler[] GetTaskSchedulersForDebugger()
{
if (s_activeTaskSchedulers == null)
/// <summary>
- /// A TaskScheduler implementation that executes all tasks queued to it through a call to
- /// <see cref="System.Threading.SynchronizationContext.Post"/> on the <see cref="T:System.Threading.SynchronizationContext"/>
- /// that its associated with. The default constructor for this class binds to the current <see cref="T:System.Threading.SynchronizationContext"/>
+ /// A TaskScheduler implementation that executes all tasks queued to it through a call to
+ /// <see cref="System.Threading.SynchronizationContext.Post"/> on the <see cref="T:System.Threading.SynchronizationContext"/>
+ /// that its associated with. The default constructor for this class binds to the current <see cref="T:System.Threading.SynchronizationContext"/>
/// </summary>
internal sealed class SynchronizationContextTaskScheduler : TaskScheduler
{
private SynchronizationContext m_synchronizationContext;
/// <summary>
- /// Constructs a SynchronizationContextTaskScheduler associated with <see cref="T:System.Threading.SynchronizationContext.Current"/>
+ /// Constructs a SynchronizationContextTaskScheduler associated with <see cref="T:System.Threading.SynchronizationContext.Current"/>
/// </summary>
/// <exception cref="T:System.InvalidOperationException">This constructor expects <see cref="T:System.Threading.SynchronizationContext.Current"/> to be set.</exception>
internal SynchronizationContextTaskScheduler()
/// <summary>
/// Implementation of <see cref="T:System.Threading.Tasks.TaskScheduler.QueueTask"/> for this scheduler class.
- ///
+ ///
/// Simply posts the tasks to be executed on the associated <see cref="T:System.Threading.SynchronizationContext"/>.
/// </summary>
/// <param name="task"></param>
/// <summary>
/// Implementation of <see cref="T:System.Threading.Tasks.TaskScheduler.TryExecuteTaskInline"/> for this scheduler class.
- ///
- /// The task will be executed inline only if the call happens within
+ ///
+ /// The task will be executed inline only if the call happens within
/// the associated <see cref="T:System.Threading.SynchronizationContext"/>.
/// </summary>
/// <param name="task"></param>
/// <summary>
/// Implements the <see cref="T:System.Threading.Tasks.TaskScheduler.MaximumConcurrencyLevel"/> property for
/// this scheduler class.
- ///
+ ///
/// By default it returns 1, because a <see cref="T:System.Threading.SynchronizationContext"/> based
/// scheduler only supports execution on a single thread.
/// </summary>
/// <summary>
/// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskSchedulerException"/> class.
/// </summary>
- public TaskSchedulerException() : base(SR.TaskSchedulerException_ctor_DefaultMessage) //
+ public TaskSchedulerException() : base(SR.TaskSchedulerException_ctor_DefaultMessage) //
{
}
// Assuming we're in the default ExecutionContext, the "slow path" of an incomplete
// task will result in four allocations: the new IAsyncResult, the delegate+closure
// in this method, and the continuation object inside of OnCompleted (necessary
- // to capture both the Action delegate and the ExecutionContext in a single object).
- // In the future, if performance requirements drove a need, those four
+ // to capture both the Action delegate and the ExecutionContext in a single object).
+ // In the future, if performance requirements drove a need, those four
// allocations could be reduced to one. This would be achieved by having TaskWrapperAsyncResult
// also implement ITaskCompletionAction (and optionally IThreadPoolWorkItem). It would need
- // additional fields to store the AsyncCallback and an ExecutionContext. Once configured,
- // it would be set into the Task as a continuation. Its Invoke method would then be run when
- // the antecedent completed, and, doing all of the necessary work to flow ExecutionContext,
- // it would invoke the AsyncCallback. It could also have a field on it for the antecedent,
- // so that the End method would have access to the completed antecedent. For related examples,
- // see other implementations of ITaskCompletionAction, and in particular ReadWriteTask
+ // additional fields to store the AsyncCallback and an ExecutionContext. Once configured,
+ // it would be set into the Task as a continuation. Its Invoke method would then be run when
+ // the antecedent completed, and, doing all of the necessary work to flow ExecutionContext,
+ // it would invoke the AsyncCallback. It could also have a field on it for the antecedent,
+ // so that the End method would have access to the completed antecedent. For related examples,
+ // see other implementations of ITaskCompletionAction, and in particular ReadWriteTask
// used in Stream.Begin/EndXx's implementation.
}
_completedSynchronously = completedSynchronously;
}
- // The IAsyncResult implementation.
+ // The IAsyncResult implementation.
// - IsCompleted and AsyncWaitHandle just pass through to the Task.
// - AsyncState and CompletedSynchronously return the corresponding values stored in this object.
// TaskScheduler.cs
//
//
-// This file contains the primary interface and management of tasks and queues.
+// This file contains the primary interface and management of tasks and queues.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
/// This internal function will do this:
/// (1) If the task had previously been queued, attempt to pop it and return false if that fails.
/// (2) Return whether the task is executed
- ///
+ ///
/// IMPORTANT NOTE: TryExecuteTaskInline will NOT throw task exceptions itself. Any wait code path using this function needs
/// to account for exceptions that need to be propagated, and throw themselves accordingly.
/// </summary>
/// </summary>
public const EventKeywords TaskTransfer = (EventKeywords)1;
/// <summary>
- /// TaskTranser events plus events when tasks start and stop
+ /// TaskTranser events plus events when tasks start and stop
/// </summary>
public const EventKeywords Tasks = (EventKeywords)2;
/// <summary>
/// <summary>
/// TasksFlowActivityIds indicate that activity ID flow from one task
- /// to any task created by it.
+ /// to any task created by it.
/// </summary>
public const EventKeywords TasksFlowActivityIds = (EventKeywords)0x80;
public const EventKeywords AsyncMethod = (EventKeywords)0x100;
/// <summary>
- /// TasksSetActivityIds will cause the task operations to set Activity Ids
+ /// TasksSetActivityIds will cause the task operations to set Activity Ids
/// This option is incompatible with TasksFlowActivityIds flow is ignored
/// if that keyword is set. This option is likely to be removed in the future
/// </summary>
private const EventKeywords ALL_KEYWORDS = (EventKeywords)(-1);
//-----------------------------------------------------------------------------------
- //
+ //
// TPL Event IDs (must be unique)
//
//-----------------------------------------------------------------------------------
- //
+ //
// Task Events
//
- // These are all verbose events, so we need to call IsEnabled(EventLevel.Verbose, ALL_KEYWORDS)
- // call. However since the IsEnabled(l,k) call is more expensive than IsEnabled(), we only want
+ // These are all verbose events, so we need to call IsEnabled(EventLevel.Verbose, ALL_KEYWORDS)
+ // call. However since the IsEnabled(l,k) call is more expensive than IsEnabled(), we only want
// to incur this cost when instrumentation is enabled. So the Task codepaths that call these
// event functions still do the check for IsEnabled()
int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
int TaskID, int CreatingTaskID, int TaskCreationOptions, int appDomain = DefaultAppDomainID)
{
- // IsEnabled() call is an inlined quick check that makes this very fast when provider is off
+ // IsEnabled() call is an inlined quick check that makes this very fast when provider is off
if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.TaskTransfer | Keywords.Tasks))
{
unsafe
/// <param name="TaskID">The task ID.</param>
/// <param name="Behavior">Configured behavior for the wait.</param>
/// <param name="ContinueWithTaskID">
- /// If known, if 'TaskID' has a 'continueWith' task, mention give its ID here.
+ /// If known, if 'TaskID' has a 'continueWith' task, mention give its ID here.
/// 0 means unknown. This allows better visualization of the common sequential chaining case.
/// </param>
[Event(TASKWAITBEGIN_ID, Version = 3, Task = TplEventSource.Tasks.TaskWait, Opcode = EventOpcode.Send,
int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
int TaskID)
{
- // Log an event if indicated.
+ // Log an event if indicated.
if (IsEnabled() && IsEnabled(EventLevel.Verbose, Keywords.Tasks))
WriteEvent(TASKWAITEND_ID, OriginatingTaskSchedulerID, OriginatingTaskID, TaskID);
}
Level = EventLevel.Verbose, Keywords = Keywords.TaskStops)]
public void TaskWaitContinuationComplete(int TaskID)
{
- // Log an event if indicated.
+ // Log an event if indicated.
if (IsEnabled() && IsEnabled(EventLevel.Verbose, Keywords.Tasks))
WriteEvent(TASKWAITCONTINUATIONCOMPLETE_ID, TaskID);
}
Level = EventLevel.Verbose, Keywords = Keywords.TaskStops)]
public void TaskWaitContinuationStarted(int TaskID)
{
- // Log an event if indicated.
+ // Log an event if indicated.
if (IsEnabled() && IsEnabled(EventLevel.Verbose, Keywords.Tasks))
WriteEvent(TASKWAITCONTINUATIONSTARTED_ID, TaskID);
}
{
// The thread pool generated a process wide unique GUID from a task GUID by
// using the taskGuid, the appdomain ID, and 8 bytes of 'randomization' chosen by
- // using the last 8 bytes as the provider GUID for this provider.
+ // using the last 8 bytes as the provider GUID for this provider.
// These were generated by CreateGuid, and are reasonably random (and thus unlikely to collide
uint pid = EventSource.s_currentPid;
return new Guid(taskID,
{
object? obj = _obj;
Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
- return
+ return
obj == null ? CompletedTask :
obj as Task ??
GetTaskForValueTaskSource(Unsafe.As<IValueTaskSource>(obj));
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
-// A class that provides a simple, lightweight implementation of thread-local lazy-initialization, where a value is initialized once per accessing
-// thread; this provides an alternative to using a ThreadStatic static variable and having
+// A class that provides a simple, lightweight implementation of thread-local lazy-initialization, where a value is initialized once per accessing
+// thread; this provides an alternative to using a ThreadStatic static variable and having
// to check the variable prior to every access to see if it's been initialized.
namespace System.Threading
/// <typeparam name="T">Specifies the type of data stored per-thread.</typeparam>
/// <remarks>
/// <para>
- /// With the exception of <see cref="Dispose()"/>, all public and protected members of
+ /// With the exception of <see cref="Dispose()"/>, all public and protected members of
/// <see cref="ThreadLocal{T}"/> are thread-safe and may be used
/// concurrently from multiple threads.
/// </para>
private static readonly IdManager s_idManager = new IdManager();
// A linked list of all values associated with this ThreadLocal<T> instance.
- // We create a dummy head node. That allows us to remove any (non-dummy) node without having to locate the m_linkedSlot field.
+ // We create a dummy head node. That allows us to remove any (non-dummy) node without having to locate the m_linkedSlot field.
private LinkedSlot? _linkedSlot = new LinkedSlot(null);
// Whether the Values property is supported
/// specified <paramref name="valueFactory"/> function.
/// </summary>
/// <param name="valueFactory">
- /// The <see cref="T:System.Func{T}"/> invoked to produce a lazily-initialized value when
+ /// The <see cref="T:System.Func{T}"/> invoked to produce a lazily-initialized value when
/// an attempt is made to retrieve <see cref="Value"/> without it having been previously initialized.
/// </param>
/// <exception cref="T:System.ArgumentNullException">
/// specified <paramref name="valueFactory"/> function.
/// </summary>
/// <param name="valueFactory">
- /// The <see cref="T:System.Func{T}"/> invoked to produce a lazily-initialized value when
+ /// The <see cref="T:System.Func{T}"/> invoked to produce a lazily-initialized value when
/// an attempt is made to retrieve <see cref="Value"/> without it having been previously initialized.
/// </param>
/// <param name="trackAllValues">Whether to track all values set on the instance and expose them via the Values property.</param>
/// </exception>
/// <remarks>
/// If this instance was not previously initialized for the current thread,
- /// accessing <see cref="Value"/> will attempt to initialize it. If an initialization function was
- /// supplied during the construction, that initialization will happen by invoking the function
- /// to retrieve the initial value for <see cref="Value"/>. Otherwise, the default value of
+ /// accessing <see cref="Value"/> will attempt to initialize it. If an initialization function was
+ /// supplied during the construction, that initialization will happen by invoking the function
+ /// to retrieve the initial value for <see cref="Value"/>. Otherwise, the default value of
/// <typeparamref name="T"/> will be used.
/// </remarks>
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
{
// We verified that the instance has not been disposed *after* we got a reference to the slot.
// This guarantees that we have a reference to the right slot.
- //
+ //
// Volatile read of the LinkedSlotVolatile.Value property ensures that the m_initialized read
// will not be reordered before the read of slotArray[id].
return slot._value;
{
// We verified that the instance has not been disposed *after* we got a reference to the slot.
// This guarantees that we have a reference to the right slot.
- //
+ //
// Volatile read of the LinkedSlotVolatile.Value property ensures that the m_initialized read
// will not be reordered before the read of slotArray[id].
slot._value = value;
Debug.Assert(_linkedSlot != null, "Should only be null if disposed");
LinkedSlot? firstRealNode = _linkedSlot._next;
- // Insert linkedSlot between nodes m_linkedSlot and firstRealNode.
+ // Insert linkedSlot between nodes m_linkedSlot and firstRealNode.
// (_linkedSlot is the dummy head node that should always be in the front.)
linkedSlot._next = firstRealNode;
linkedSlot._previous = _linkedSlot;
LinkedSlotVolatile[] newTable = new LinkedSlotVolatile[newLen];
//
- // The lock is necessary to avoid a race with ThreadLocal.Dispose. GrowTable has to point all
- // LinkedSlot instances referenced in the old table to reference the new table. Without locking,
- // Dispose could use a stale SlotArray reference and clear out a slot in the old array only, while
+ // The lock is necessary to avoid a race with ThreadLocal.Dispose. GrowTable has to point all
+ // LinkedSlot instances referenced in the old table to reference the new table. Without locking,
+ // Dispose could use a stale SlotArray reference and clear out a slot in the old array only, while
// the value continues to be referenced from the new (larger) array.
//
lock (s_idManager)
//
// Round up the size to the next power of 2
//
- // The algorithm takes three steps:
+ // The algorithm takes three steps:
// input -> subtract one -> propagate 1-bits to the right -> add one
//
- // Let's take a look at the 3 steps in both interesting cases: where the input
+ // Let's take a look at the 3 steps in both interesting cases: where the input
// is (Example 1) and isn't (Example 2) a power of 2.
//
// Example 1: 100000 -> 011111 -> 011111 -> 100000
// Example 2: 011010 -> 011001 -> 011111 -> 100000
- //
+ //
int newSize = minSize;
// Step 1: Decrement
/// <summary>
/// A node in the doubly-linked list stored in the ThreadLocal instance.
- ///
+ ///
/// The value is stored in one of two places:
- ///
+ ///
/// 1. If SlotArray is not null, the value is in SlotArray.Table[id]
/// 2. If SlotArray is null, the value is in FinalValue.
/// </summary>
/// <summary>
/// A class that facilitates ThreadLocal cleanup after a thread exits.
- ///
- /// After a thread with an associated thread-local table has exited, the FinalizationHelper
- /// is responsible for removing back-references to the table. Since an instance of FinalizationHelper
+ ///
+ /// After a thread with an associated thread-local table has exited, the FinalizationHelper
+ /// is responsible for removing back-references to the table. Since an instance of FinalizationHelper
/// is only referenced from a single thread-local slot, the FinalizationHelper will be GC'd once
/// the thread has exited.
- ///
+ ///
/// The FinalizationHelper then locates all LinkedSlot instances with back-references to the table
/// (all those LinkedSlot instances can be found by following references from the table slots) and
/// releases the table so that it can get GC'd.
}
}
- /// <summary>A debugger view of the ThreadLocal<T> to surface additional debugging properties and
+ /// <summary>A debugger view of the ThreadLocal<T> to surface additional debugging properties and
/// to ensure that the ThreadLocal<T> does not become initialized if it was not already.</summary>
internal sealed class SystemThreading_ThreadLocalDebugView<T>
{
// if head is currently < tail, it remains that way. This happens to just fall out from
// the bit-masking, because we only do this if tail == int.MaxValue, meaning that all
// bits are set, so all of the bits we're keeping will also be set. Thus it's impossible
- // for the head to end up > than the tail, since you can't set any more bits than all of
+ // for the head to end up > than the tail, since you can't set any more bits than all of
// them.
//
m_headIndex = m_headIndex & m_mask;
outerWorkQueue.loggingEnabled = FrameworkEventSource.Log.IsEnabled(EventLevel.Verbose, FrameworkEventSource.Keywords.ThreadPool | FrameworkEventSource.Keywords.ThreadTransfer);
//
- // Assume that we're going to need another thread if this one returns to the VM. We'll set this to
+ // Assume that we're going to need another thread if this one returns to the VM. We'll set this to
// false later, but only if we're absolutely certain that the queue is empty.
//
bool needAnotherThread = true;
//
// Set up our thread-local data
//
- // Use operate on workQueue local to try block so it can be enregistered
+ // Use operate on workQueue local to try block so it can be enregistered
ThreadPoolWorkQueue workQueue = outerWorkQueue;
ThreadPoolWorkQueueThreadLocals tl = workQueue.GetOrCreateThreadLocals();
Thread currentThread = tl.currentThread;
while (ThreadPool.KeepDispatching(startTickCount))
{
bool missedSteal = false;
- // Use operate on workItem local to try block so it can be enregistered
+ // Use operate on workItem local to try block so it can be enregistered
object? workItem = outerWorkItem = workQueue.Dequeue(tl, ref missedSteal);
if (workItem == null)
// No work.
// If we missed a steal, though, there may be more work in the queue.
// Instead of looping around and trying again, we'll just request another thread. Hopefully the thread
- // that owns the contended work-stealing queue will pick up its own workitems in the meantime,
+ // that owns the contended work-stealing queue will pick up its own workitems in the meantime,
// which will be more efficient than this thread doing it anyway.
//
needAnotherThread = missedSteal;
// Return to clean ExecutionContext and SynchronizationContext
ExecutionContext.ResetThreadPoolThread(currentThread);
- //
+ //
// Notify the VM that we executed this workitem. This is also our opportunity to ask whether Hill Climbing wants
// us to return the thread to the pool or not.
//
}
// If the callback is the runtime-provided invocation of an IAsyncStateMachineBox,
- // then we can queue the Task state directly to the ThreadPool instead of
+ // then we can queue the Task state directly to the ThreadPool instead of
// wrapping it in a QueueUserWorkItemCallback.
//
// This occurs when user code queues its provided continuation to the ThreadPool;
{
// The VM's timer implementation does not work well for very long-duration timers.
// So we limit our native timer duration to a "small" value.
- // This may cause us to attempt to fire timers early, but that's ok -
+ // This may cause us to attempt to fire timers early, but that's ok -
// we'll just see that none of our timers has actually reached its due time,
// and schedule the native timer again.
const uint maxPossibleDuration = 0x0fffffff;
// When Timer.Dispose(WaitHandle) is used, we need to signal the wait handle only
// after all pending callbacks are complete. We set _canceled to prevent any callbacks that
- // are already queued from running. We track the number of callbacks currently executing in
+ // are already queued from running. We track the number of callbacks currently executing in
// _callbacksRunning. We set _notifyWhenNoCallbacksRunning only when _callbacksRunning
// reaches zero. Same applies if Timer.DisposeAsync() is used, except with a Task<bool>
// instead of with a provided WaitHandle.
};
}
- // TimerHolder serves as an intermediary between Timer and TimerQueueTimer, releasing the TimerQueueTimer
+ // TimerHolder serves as an intermediary between Timer and TimerQueueTimer, releasing the TimerQueueTimer
// if the Timer is collected.
// This is necessary because Timer itself cannot use its finalizer for this purpose. If it did,
// then users could control timer lifetimes using GC.SuppressFinalize/ReRegisterForFinalize.
int dueTime = -1; // We want timer to be registered, but not activated. Requires caller to call
int period = -1; // Change after a timer instance is created. This is to avoid the potential
// for a timer to be fired before the returned value is assigned to the variable,
- // potentially causing the callback to reference a bogus value (if passing the timer to the callback).
+ // potentially causing the callback to reference a bogus value (if passing the timer to the callback).
TimerSetup(callback, this, (uint)dueTime, (uint)period);
}
if (value == InvalidHandle)
{
// This line leaks a handle. However, it's currently
- // not perfectly clear what the right behavior is here
- // anyways. This preserves Everett behavior. We should
+ // not perfectly clear what the right behavior is here
+ // anyways. This preserves Everett behavior. We should
// ideally do these things:
// *) Expose a settable SafeHandle property on WaitHandle.
// *) Expose a settable OwnsHandle property on SafeHandle.
return totalSeconds * TicksPerSecond;
}
- // See System.Globalization.TimeSpanParse and System.Globalization.TimeSpanFormat
+ // See System.Globalization.TimeSpanParse and System.Globalization.TimeSpanFormat
#region ParseAndFormat
private static void ValidateStyles(TimeSpanStyles style, string parameterName)
{
**
**
**
-** Purpose:
+** Purpose:
** This class is used to represent a TimeZone. It
** has methods for converting a DateTime to UTC from local time
-** and to local time from UTC and methods for getting the
-** standard name and daylight name of the time zone.
+** and to local time from UTC and methods for getting the
+** standard name and daylight name of the time zone.
**
-** The only TimeZone that we support in version 1 is the
+** The only TimeZone that we support in version 1 is the
** CurrentTimeZone as determined by the system timezone.
**
**
}
//This method is called by CultureInfo.ClearCachedData in response to control panel
- //change events. It must be synchronized because otherwise there is a race condition
+ //change events. It must be synchronized because otherwise there is a race condition
//with the CurrentTimeZone property above.
internal static void ResetTimeZone()
{
public abstract TimeSpan GetUtcOffset(DateTime time);
//
- // Converts the specified datatime to the Universal time base on the current timezone
+ // Converts the specified datatime to the Universal time base on the current timezone
//
public virtual DateTime ToUniversalTime(DateTime time)
{
//
// NOTENOTE: Implementation detail
- // In the transition from standard time to daylight saving time,
+ // In the transition from standard time to daylight saving time,
// if we convert local time to Universal time, we can have the
// following (take PST as an example):
// Local Universal UTC Offset
// 03:00 10:00 -7:00
// 04:00 11:00 -7:00
// 05:00 12:00 -7:00
- //
+ //
// So from 02:00 - 02:59:59, we should return the standard offset, instead of the daylight saving offset.
//
// In the transition from daylight saving time to standard time,
// Local Universal UTC Offset
// ----- --------- ----------
// 01:00AM 08:00 -7:00
- // 02:00 (=> 01:00) 09:00 -8:00
+ // 02:00 (=> 01:00) 09:00 -8:00
// 02:00 10:00 -8:00
// 03:00 11:00 -8:00
// 04:00 12:00 -8:00
- //
+ //
// So in this case, the 02:00 does exist after the first 2:00 rolls back to 01:00. We don't need to special case this.
// But note that there are two 01:00 in the local time.
//
// And imagine if the daylight saving offset is negative (although this does not exist in real life)
- // In the transition from standard time to daylight saving time,
+ // In the transition from standard time to daylight saving time,
// if we convert local time to Universal time, we can have the
// following (take PST as an example, but the daylight saving offset is -01:00):
// Local Universal UTC Offset
// 03:00 12:00 -9:00
// 04:00 13:00 -9:00
// 05:00 14:00 -9:00
- //
+ //
// So in this case, the 02:00 does exist after the first 2:00 rolls back to 01:00. We don't need to special case this.
//
// In the transition from daylight saving time to standard time,
// 04:00 12:00 -8:00
// 05:00 13:00 -8:00
// 06:00 14:00 -8:00
- //
+ //
// So from 02:00 - 02:59:59, we should return the daylight saving offset, instead of the standard offset.
//
internal static TimeSpan CalculateUtcOffset(DateTime time, DaylightTime daylightTimes)
DateTime startTime;
DateTime endTime;
- // startTime and endTime represent the period from either the start of DST to the end and includes the
+ // startTime and endTime represent the period from either the start of DST to the end and includes the
// potentially overlapped times
startTime = daylightTimes.Start + daylightTimes.Delta;
endTime = daylightTimes.End;
- // For normal time zones, the ambiguous hour is the last hour of daylight saving when you wind the
+ // For normal time zones, the ambiguous hour is the last hour of daylight saving when you wind the
// clock back. It is theoretically possible to have a positive delta, (which would really be daylight
// reduction time), where you would have to wind the clock back in the begnning.
DateTime ambiguousStart;
}
// If this date was previously converted from a UTC date and we were able to detect that the local
- // DateTime would be ambiguous, this data is stored in the DateTime to resolve this ambiguity.
+ // DateTime would be ambiguous, this data is stored in the DateTime to resolve this ambiguity.
if (isDst && time >= ambiguousStart && time < ambiguousEnd)
{
isDst = time.IsAmbiguousDaylightSavingTime();
try
{
EnumerateFilesRecursively(timeZoneDirectory, (string filePath) =>
- {
+ {
// skip the localtime and posixrules file, since they won't give us the correct id
if (!string.Equals(filePath, localtimeFilePath, StringComparison.OrdinalIgnoreCase)
&& !string.Equals(filePath, posixrulesFilePath, StringComparison.OrdinalIgnoreCase))
{
if (date[0] != 'J')
{
- // should be n Julian day format which we don't support.
- //
+ // should be n Julian day format which we don't support.
+ //
// This specifies the Julian day, with n between 0 and 365. February 29 is counted in leap years.
//
- // n would be a relative number from the begining of the year. which should handle if the
+ // n would be a relative number from the begining of the year. which should handle if the
// the year is a leap year or not.
- //
+ //
// In leap year, n would be counted as:
- //
+ //
// 0 30 31 59 60 90 335 365
// |-------Jan--------|-------Feb--------|-------Mar--------|....|-------Dec--------|
//
- // while in non leap year we'll have
- //
+ // while in non leap year we'll have
+ //
// 0 30 31 58 59 89 334 364
// |-------Jan--------|-------Feb--------|-------Mar--------|....|-------Dec--------|
//
- //
+ //
// For example if n is specified as 60, this means in leap year the rule will start at Mar 1,
// while in non leap year the rule will start at Mar 2.
- //
+ //
// If we need to support n format, we'll have to have a floating adjustment rule support this case.
throw new InvalidTimeZoneException(SR.InvalidTimeZone_NJulianDayNotSupported);
return true;
// For backward-compatibility, we need to special case for the types
- // whose UnderlyingSystemType are runtime implemented.
+ // whose UnderlyingSystemType are runtime implemented.
Type toType = this.UnderlyingSystemType;
if (toType?.IsRuntimeImplemented() == true)
return toType.IsAssignableFrom(c);
}
}
}
-
{
HResult = HResults.COR_E_TYPEUNLOADED;
}
-
+
protected TypeUnloadedException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
}
-
**
**
**
-** Purpose: An exception for OS 'access denied' types of
-** errors, including IO and limited security types
+** Purpose: An exception for OS 'access denied' types of
+** errors, including IO and limited security types
** of errors.
**
-**
+**
===========================================================*/
using System.Runtime.Serialization;
namespace System
{
- // The UnauthorizedAccessException is thrown when access errors
+ // The UnauthorizedAccessException is thrown when access errors
// occur from IO or other OS methods.
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
private readonly string? _data;
/// <summary>
- /// A helper method that returns the SerializationInfo that a class utilizing
+ /// A helper method that returns the SerializationInfo that a class utilizing
/// UnitySerializationHelper should return from a call to GetObjectData. It contains
/// the unityType (defined above) and any optional data (used only for the reflection types).
/// </summary>
/// - their members (such as Item1, Item2, etc) are fields rather than properties.
/// </summary>
[Serializable]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple
: IEquatable<ValueTuple>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple>, IValueTupleInternal, ITuple
{
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
- /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
+ /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple other)
/// <summary>Represents a 1-tuple, or singleton, as a value type.</summary>
/// <typeparam name="T1">The type of the tuple's only component.</typeparam>
[Serializable]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1>
: IEquatable<ValueTuple<T1>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1>>, IValueTupleInternal, ITuple
{
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
- /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
+ /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple<T1> other)
/// <typeparam name="T2">The type of the tuple's second component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2>
: IEquatable<ValueTuple<T1, T2>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2>>, IValueTupleInternal, ITuple
{
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
- /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
+ /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple<T1, T2> other)
/// <typeparam name="T3">The type of the tuple's third component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3>
: IEquatable<ValueTuple<T1, T2, T3>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3>>, IValueTupleInternal, ITuple
{
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
- /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
+ /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple<T1, T2, T3> other)
/// <typeparam name="T4">The type of the tuple's fourth component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3, T4>
: IEquatable<ValueTuple<T1, T2, T3, T4>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4>>, IValueTupleInternal, ITuple
{
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
- /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
+ /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple<T1, T2, T3, T4> other)
/// <typeparam name="T5">The type of the tuple's fifth component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3, T4, T5>
: IEquatable<ValueTuple<T1, T2, T3, T4, T5>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5>>, IValueTupleInternal, ITuple
{
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
- /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
+ /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple<T1, T2, T3, T4, T5> other)
/// <typeparam name="T6">The type of the tuple's sixth component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3, T4, T5, T6>
: IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5, T6>>, IValueTupleInternal, ITuple
{
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
- /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
+ /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple<T1, T2, T3, T4, T5, T6> other)
/// <typeparam name="T7">The type of the tuple's seventh component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3, T4, T5, T6, T7>
: IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6, T7>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5, T6, T7>>, IValueTupleInternal, ITuple
{
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
- /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
+ /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple<T1, T2, T3, T4, T5, T6, T7> other)
/// <typeparam name="TRest">The type of the tuple's eighth component.</typeparam>
[Serializable]
[StructLayout(LayoutKind.Auto)]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public struct ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>
: IEquatable<ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable<ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest>>, IValueTupleInternal, ITuple
where TRest : struct
/// <returns>
/// A signed number indicating the relative values of this instance and <paramref name="other"/>.
/// Returns less than zero if this instance is less than <paramref name="other"/>, zero if this
- /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
+ /// instance is equal to <paramref name="other"/>, and greater than zero if this instance is greater
/// than <paramref name="other"/>.
/// </returns>
public int CompareTo(ValueTuple<T1, T2, T3, T4, T5, T6, T7, TRest> other)
namespace System
{
// A Version object contains four hierarchical numeric components: major, minor,
- // build and revision. Build and revision may be unspecified, which is represented
- // internally as a -1. By definition, an unspecified component matches anything
+ // build and revision. Build and revision may be unspecified, which is represented
+ // internally as a -1. By definition, an unspecified component matches anything
// (both unspecified and specified), and an unspecified component is "less than" any
// specified component.
namespace System
{
[Serializable]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
// This class is sealed to mitigate security issues caused by Object::MemberwiseClone.
public sealed partial class WeakReference<T> : ISerializable
where T : class?