diff options
Diffstat (limited to 'src/mscorlib/src/System')
719 files changed, 12511 insertions, 72763 deletions
diff --git a/src/mscorlib/src/System/AccessViolationException.cs b/src/mscorlib/src/System/AccessViolationException.cs index 308d52e9ed..12911c1b17 100644 --- a/src/mscorlib/src/System/AccessViolationException.cs +++ b/src/mscorlib/src/System/AccessViolationException.cs @@ -11,41 +11,38 @@ ** =============================================================================*/ -namespace System -{ - - using System; - using System.Runtime.Serialization; - [System.Runtime.InteropServices.ComVisible(true)] +using System; +using System.Runtime.Serialization; + +namespace System +{ [Serializable] - public class AccessViolationException : SystemException + public class AccessViolationException : SystemException { - public AccessViolationException() - : base(Environment.GetResourceString("Arg_AccessViolationException")) + public AccessViolationException() + : base(SR.Arg_AccessViolationException) { - SetErrorCode(__HResults.E_POINTER); + HResult = __HResults.E_POINTER; } - - public AccessViolationException(String message) - : base(message) + + public AccessViolationException(String message) + : base(message) { - SetErrorCode(__HResults.E_POINTER); + HResult = __HResults.E_POINTER; } - - public AccessViolationException(String message, Exception innerException) - : base(message, innerException) + + public AccessViolationException(String message, Exception innerException) + : base(message, innerException) { - SetErrorCode(__HResults.E_POINTER); + HResult = __HResults.E_POINTER; } - protected AccessViolationException(SerializationInfo info, StreamingContext context) : base(info, context) {} + protected AccessViolationException(SerializationInfo info, StreamingContext context) : base(info, context) { } #pragma warning disable 169 // Field is not used from managed. private IntPtr _ip; // Address of faulting instruction. private IntPtr _target; // Address that could not be accessed. private int _accessType; // 0:read, 1:write #pragma warning restore 169 - } - } diff --git a/src/mscorlib/src/System/Action.cs b/src/mscorlib/src/System/Action.cs index 27f7fafe5c..23c7e93194 100644 --- a/src/mscorlib/src/System/Action.cs +++ b/src/mscorlib/src/System/Action.cs @@ -6,8 +6,6 @@ namespace System { public delegate void Action<in T>(T obj); - // Action/Func delegates first shipped with .NET Framework 3.5 in System.Core.dll as part of LINQ - // These were type forwarded to mscorlib.dll in .NET Framework 4.0 and in Silverlight 5.0 public delegate void Action(); public delegate void Action<in T1,in T2>(T1 arg1, T2 arg2); public delegate void Action<in T1,in T2,in T3>(T1 arg1, T2 arg2, T3 arg3); @@ -32,8 +30,6 @@ namespace System public delegate int Comparison<in T>(T x, T y); public delegate TOutput Converter<in TInput, out TOutput>(TInput input); - - public delegate bool Predicate<in T>(T obj); + public delegate bool Predicate<in T>(T obj); } - diff --git a/src/mscorlib/src/System/Activator.cs b/src/mscorlib/src/System/Activator.cs index 6fad8f3173..323fbba9cc 100644 --- a/src/mscorlib/src/System/Activator.cs +++ b/src/mscorlib/src/System/Activator.cs @@ -22,16 +22,12 @@ namespace System { using StackCrawlMark = System.Threading.StackCrawlMark; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; - using System.Security.Permissions; using AssemblyHashAlgorithm = System.Configuration.Assemblies.AssemblyHashAlgorithm; using System.Runtime.Versioning; using System.Diagnostics.Contracts; // Only statics, does not need to be marked with the serializable attribute - [ClassInterface(ClassInterfaceType.None)] - [ComDefaultInterface(typeof(_Activator))] - [System.Runtime.InteropServices.ComVisible(true)] - public sealed class Activator : _Activator + public sealed class Activator { internal const int LookupMask = 0x000000FF; internal const BindingFlags ConLookup = (BindingFlags) (BindingFlags.Instance | BindingFlags.Public); @@ -209,31 +205,6 @@ namespace System { null, activationAttributes); } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstance which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - static public ObjectHandle CreateInstance(String assemblyName, - String typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - Object[] args, - CultureInfo culture, - Object[] activationAttributes, - Evidence securityInfo) - { - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return CreateInstance(assemblyName, - typeName, - ignoreCase, - bindingAttr, - binder, - args, - culture, - activationAttributes, - securityInfo, - ref stackMark); - } [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable public static ObjectHandle CreateInstance(string assemblyName, @@ -286,7 +257,7 @@ namespace System { // Classic managed type assembly = RuntimeAssembly.InternalLoadAssemblyName( assemblyName, securityInfo, null, ref stackMark, - true /*thrownOnFileNotFound*/, false /*forIntrospection*/, false /*suppressSecurityChecks*/); + true /*thrownOnFileNotFound*/, false /*forIntrospection*/); } } @@ -314,29 +285,6 @@ namespace System { } } - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstanceFrom which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - static public ObjectHandle CreateInstanceFrom(String assemblyFile, - String typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - Object[] args, - CultureInfo culture, - Object[] activationAttributes, - Evidence securityInfo) - - { - return CreateInstanceFromInternal(assemblyFile, - typeName, - ignoreCase, - bindingAttr, - binder, - args, - culture, - activationAttributes, - securityInfo); - } - public static ObjectHandle CreateInstanceFrom(string assemblyFile, string typeName, bool ignoreCase, @@ -388,120 +336,6 @@ namespace System { } } - // - // This API is designed to be used when a host needs to execute code in an AppDomain - // with restricted security permissions. In that case, we demand in the client domain - // and assert in the server domain because the server domain might not be trusted enough - // to pass the security checks when activating the type. - // - - public static ObjectHandle CreateInstance (AppDomain domain, string assemblyName, string typeName) { - if (domain == null) - throw new ArgumentNullException(nameof(domain)); - Contract.EndContractBlock(); - return domain.InternalCreateInstanceWithNoSecurity(assemblyName, typeName); - } - - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstance which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public static ObjectHandle CreateInstance (AppDomain domain, - string assemblyName, - string typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - Object[] args, - CultureInfo culture, - Object[] activationAttributes, - Evidence securityAttributes) { - if (domain == null) - throw new ArgumentNullException(nameof(domain)); - Contract.EndContractBlock(); - - return domain.InternalCreateInstanceWithNoSecurity(assemblyName, typeName, ignoreCase, bindingAttr, binder, args, culture, activationAttributes, securityAttributes); - } - - public static ObjectHandle CreateInstance(AppDomain domain, - string assemblyName, - string typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - object[] args, - CultureInfo culture, - object[] activationAttributes) - { - if (domain == null) - throw new ArgumentNullException(nameof(domain)); - Contract.EndContractBlock(); - - return domain.InternalCreateInstanceWithNoSecurity(assemblyName, - typeName, - ignoreCase, - bindingAttr, - binder, - args, - culture, - activationAttributes, - null); - } - - // - // This API is designed to be used when a host needs to execute code in an AppDomain - // with restricted security permissions. In that case, we demand in the client domain - // and assert in the server domain because the server domain might not be trusted enough - // to pass the security checks when activating the type. - // - - public static ObjectHandle CreateInstanceFrom (AppDomain domain, string assemblyFile, string typeName) { - if (domain == null) - throw new ArgumentNullException(nameof(domain)); - Contract.EndContractBlock(); - return domain.InternalCreateInstanceFromWithNoSecurity(assemblyFile, typeName); - } - - [Obsolete("Methods which use Evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstanceFrom which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public static ObjectHandle CreateInstanceFrom (AppDomain domain, - string assemblyFile, - string typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - Object[] args, - CultureInfo culture, - Object[] activationAttributes, - Evidence securityAttributes) { - if (domain == null) - throw new ArgumentNullException(nameof(domain)); - Contract.EndContractBlock(); - - return domain.InternalCreateInstanceFromWithNoSecurity(assemblyFile, typeName, ignoreCase, bindingAttr, binder, args, culture, activationAttributes, securityAttributes); - } - - public static ObjectHandle CreateInstanceFrom(AppDomain domain, - string assemblyFile, - string typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - object[] args, - CultureInfo culture, - object[] activationAttributes) - { - if (domain == null) - throw new ArgumentNullException(nameof(domain)); - Contract.EndContractBlock(); - - return domain.InternalCreateInstanceFromWithNoSecurity(assemblyFile, - typeName, - ignoreCase, - bindingAttr, - binder, - args, - culture, - activationAttributes, - null); - } - public static ObjectHandle CreateComInstanceFrom(String assemblyName, String typeName) { @@ -553,28 +387,6 @@ namespace System { private static void Log(bool test, string title, string success, string failure) { } - - void _Activator.GetTypeInfoCount(out uint pcTInfo) - { - throw new NotImplementedException(); - } - - void _Activator.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) - { - throw new NotImplementedException(); - } - - void _Activator.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) - { - throw new NotImplementedException(); - } - - // If you implement this method, make sure to include _Activator.Invoke in VM\DangerousAPIs.h and - // include _Activator in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp. - void _Activator.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) - { - throw new NotImplementedException(); - } } } diff --git a/src/mscorlib/src/System/AppContext/AppContext.cs b/src/mscorlib/src/System/AppContext/AppContext.cs index 41e44508f0..5a3b732fa8 100644 --- a/src/mscorlib/src/System/AppContext/AppContext.cs +++ b/src/mscorlib/src/System/AppContext/AppContext.cs @@ -19,6 +19,16 @@ namespace System } private static readonly Dictionary<string, SwitchValueState> s_switchMap = new Dictionary<string, SwitchValueState>(); + static AppContext() + { + // Unloading event must happen before ProcessExit event + AppDomain.CurrentDomain.ProcessExit += OnUnloading; + AppDomain.CurrentDomain.ProcessExit += OnProcessExit; + + // populate the AppContext with the default set of values + AppContextDefaultValues.PopulateDefaultValues(); + } + public static string BaseDirectory { get @@ -73,25 +83,28 @@ namespace System } } - public static event System.EventHandler ProcessExit - { - add - { - AppDomain.CurrentDomain.ProcessExit += value; - } - remove - { - AppDomain.CurrentDomain.ProcessExit -= value; - } + public static event System.EventHandler ProcessExit; + internal static event System.EventHandler Unloading; + + private static void OnProcessExit(object sender, EventArgs e) + { + var processExit = ProcessExit; + if (processExit != null) + { + processExit(null, EventArgs.Empty); + } } - #region Switch APIs - static AppContext() + private static void OnUnloading(object sender, EventArgs e) { - // populate the AppContext with the default set of values - AppContextDefaultValues.PopulateDefaultValues(); + var unloading = Unloading; + if (unloading != null) + { + unloading(null, EventArgs.Empty); + } } + #region Switch APIs /// <summary> /// Try to get the value of the switch. /// </summary> diff --git a/src/mscorlib/src/System/AppDomain.cs b/src/mscorlib/src/System/AppDomain.cs index fe524c4dc5..c6987392d5 100644 --- a/src/mscorlib/src/System/AppDomain.cs +++ b/src/mscorlib/src/System/AppDomain.cs @@ -20,9 +20,7 @@ namespace System using System.Runtime; using System.Runtime.CompilerServices; using System.Security; - using System.Security.Permissions; using System.Security.Policy; - using System.Security.Util; using System.Collections; using System.Collections.Generic; using System.Threading; @@ -37,11 +35,8 @@ namespace System using System.Runtime.Versioning; using System.Diagnostics; using System.Diagnostics.Contracts; -#if FEATURE_EXCEPTION_NOTIFICATIONS using System.Runtime.ExceptionServices; -#endif // FEATURE_EXCEPTION_NOTIFICATIONS - [ComVisible(true)] public class ResolveEventArgs : EventArgs { private String _Name; @@ -73,7 +68,6 @@ namespace System } } - [ComVisible(true)] public class AssemblyLoadEventArgs : EventArgs { private Assembly _LoadedAssembly; @@ -91,16 +85,13 @@ namespace System } [Serializable] - [ComVisible(true)] public delegate Assembly ResolveEventHandler(Object sender, ResolveEventArgs args); [Serializable] - [ComVisible(true)] public delegate void AssemblyLoadEventHandler(Object sender, AssemblyLoadEventArgs args); [Serializable] - [ComVisible(true)] - public delegate void AppDomainInitializer(string[] args); + internal delegate void AppDomainInitializer(string[] args); internal class AppDomainInitializerInfo { @@ -161,7 +152,6 @@ namespace System if (Info==null) return null; AppDomainInitializer retVal=null; - new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert(); for (int i=0;i<Info.Length;i++) { Assembly assembly=Assembly.Load(Info[i].TargetTypeAssembly); @@ -177,12 +167,7 @@ namespace System } } - - [ClassInterface(ClassInterfaceType.None)] - [ComDefaultInterface(typeof(System._AppDomain))] - [ComVisible(true)] - public sealed class AppDomain : - _AppDomain, IEvidenceFactory + internal sealed class AppDomain { // Domain security information // These fields initialized from the other side only. (NOTE: order @@ -190,13 +175,12 @@ namespace System // the EE- AppDomainBaseObject in this case) private AppDomainManager _domainManager; - private Dictionary<String, Object[]> _LocalStore; + private Dictionary<String, Object> _LocalStore; private AppDomainSetup _FusionStore; private Evidence _SecurityIdentity; #pragma warning disable 169 private Object[] _Policies; // Called from the VM. #pragma warning restore 169 - [method: System.Security.SecurityCritical] public event AssemblyLoadEventHandler AssemblyLoad; private ResolveEventHandler _TypeResolve; @@ -263,7 +247,6 @@ namespace System } #if FEATURE_REFLECTION_ONLY_LOAD - [method: System.Security.SecurityCritical] public event ResolveEventHandler ReflectionOnlyAssemblyResolve; #endif // FEATURE_REFLECTION_ONLY @@ -279,10 +262,8 @@ namespace System // keys, the vhe values are ignored. private Dictionary<String, object> _compatFlags; -#if FEATURE_EXCEPTION_NOTIFICATIONS // Delegate that will hold references to FirstChance exception notifications private EventHandler<FirstChanceExceptionEventArgs> _firstChanceException; -#endif // FEATURE_EXCEPTION_NOTIFICATIONS private IntPtr _pDomain; // this is an unmanaged pointer (AppDomain * m_pDomain)` used from the VM. @@ -366,9 +347,6 @@ namespace System string assembly, string type); - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern void nSetHostSecurityManagerFlags (HostSecurityManagerOptions flags); - [SuppressUnmanagedCodeSecurity] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void SetSecurityHomogeneousFlag(AppDomainHandle domain, @@ -398,7 +376,6 @@ namespace System Debug.Assert(_domainManager == null, "_domainManager == null"); AppDomainSetup adSetup = FusionStore; -#if FEATURE_VERSIONING String trustedPlatformAssemblies = (String)(GetData("TRUSTED_PLATFORM_ASSEMBLIES")); if (trustedPlatformAssemblies != null) { @@ -427,7 +404,6 @@ namespace System } SetupBindingPaths(trustedPlatformAssemblies, platformResourceRoots, appPaths, appNiPaths, appLocalWinMD); } -#endif // FEATURE_VERSIONING string domainManagerAssembly; string domainManagerType; @@ -437,9 +413,7 @@ namespace System { try { - new PermissionSet(PermissionState.Unrestricted).Assert(); _domainManager = CreateInstanceAndUnwrap(domainManagerAssembly, domainManagerType) as AppDomainManager; - CodeAccessPermission.RevertAssert(); } catch (FileNotFoundException e) { @@ -505,35 +479,6 @@ namespace System CompatibilitySwitches.InitializeSwitches(); } - // Retrieves a possibly-cached target framework name for this appdomain. This could be set - // either by a host in native, a host in managed using an AppDomainSetup, or by the - // TargetFrameworkAttribute on the executable (VS emits its target framework moniker using this - // attribute starting in version 4). - internal String GetTargetFrameworkName() - { - String targetFrameworkName = _FusionStore.TargetFrameworkName; - - if (targetFrameworkName == null && IsDefaultAppDomain() && !_FusionStore.CheckedForTargetFrameworkName) - { - // This should only be run in the default appdomain. All other appdomains should have - // values copied from the default appdomain and/or specified by the host. - Assembly assembly = Assembly.GetEntryAssembly(); - if (assembly != null) - { - TargetFrameworkAttribute[] attrs = (TargetFrameworkAttribute[])assembly.GetCustomAttributes(typeof(TargetFrameworkAttribute)); - if (attrs != null && attrs.Length > 0) - { - Debug.Assert(attrs.Length == 1); - targetFrameworkName = attrs[0].FrameworkName; - _FusionStore.TargetFrameworkName = targetFrameworkName; - } - } - _FusionStore.CheckedForTargetFrameworkName = true; - } - - return targetFrameworkName; - } - /// <summary> /// Returns the setting of the corresponding compatibility config switch (see CreateAppDomainManager for the impact). /// </summary> @@ -605,38 +550,6 @@ namespace System } /// <summary> - /// Checks (and throws on failure) if the domain supports Assembly.LoadWithPartialName. - /// </summary> - [Pure] - internal static void CheckLoadWithPartialNameSupported(StackCrawlMark stackMark) - { -#if FEATURE_APPX - if (IsAppXModel()) - { - RuntimeAssembly callingAssembly = RuntimeAssembly.GetExecutingAssembly(ref stackMark); - bool callerIsFxAssembly = callingAssembly != null && callingAssembly.IsFrameworkAssembly(); - if (!callerIsFxAssembly) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_AppX", "Assembly.LoadWithPartialName")); - } - } -#endif - } - - /// <summary> - /// Checks (and throws on failure) if the domain supports DefinePInvokeMethod. - /// </summary> - [Pure] - internal static void CheckDefinePInvokeSupported() - { - // We don't want users to use DefinePInvokeMethod in RefEmit to bypass app store validation on allowed native libraries. -#if FEATURE_APPX - if (IsAppXModel()) - throw new NotSupportedException(Environment.GetResourceString("NotSupported_AppX", "DefinePInvokeMethod")); -#endif - } - - /// <summary> /// Checks (and throws on failure) if the domain supports Assembly.Load(byte[] ...). /// </summary> [Pure] @@ -649,26 +562,6 @@ namespace System } /// <summary> - /// Checks (and throws on failure) if the domain supports AppDomain.CreateDomain. - /// </summary> - [Pure] - internal static void CheckCreateDomainSupported() - { -#if FEATURE_APPX - // Can create a new domain in an AppX process only when DevMode is enabled and - // AssemblyLoadingCompat is not enabled (since there is no multi-domain support - // for LoadFrom and LoadFile in AppX. - if(IsAppXModel()) - { - if (!IsAppXDesignMode()) - { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_AppX", "AppDomain.CreateDomain")); - } - } -#endif - } - - /// <summary> /// Get the name of the assembly and type that act as the AppDomainManager for this domain /// </summary> internal void GetAppDomainManagerType(out string assembly, out string type) @@ -811,319 +704,6 @@ namespace System } #endif // FEATURE_REFLECTION_ONLY_LOAD - - /********************************************** - * If an AssemblyName has a public key specified, the assembly is assumed - * to have a strong name and a hash will be computed when the assembly - * is saved. - **********************************************/ - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - public AssemblyBuilder DefineDynamicAssembly( - AssemblyName name, - AssemblyBuilderAccess access) - { - Contract.Ensures(Contract.Result<AssemblyBuilder>() != null); - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return InternalDefineDynamicAssembly(name, access, null, - null, null, null, null, ref stackMark, null, SecurityContextSource.CurrentAssembly); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - public AssemblyBuilder DefineDynamicAssembly( - AssemblyName name, - AssemblyBuilderAccess access, - IEnumerable<CustomAttributeBuilder> assemblyAttributes) - { - Contract.Ensures(Contract.Result<AssemblyBuilder>() != null); - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return InternalDefineDynamicAssembly(name, - access, - null, null, null, null, null, - ref stackMark, - assemblyAttributes, SecurityContextSource.CurrentAssembly); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Due to the stack crawl mark - public AssemblyBuilder DefineDynamicAssembly(AssemblyName name, - AssemblyBuilderAccess access, - IEnumerable<CustomAttributeBuilder> assemblyAttributes, - SecurityContextSource securityContextSource) - { - Contract.Ensures(Contract.Result<AssemblyBuilder>() != null); - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return InternalDefineDynamicAssembly(name, - access, - null, null, null, null, null, - ref stackMark, - assemblyAttributes, - securityContextSource); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - public AssemblyBuilder DefineDynamicAssembly( - AssemblyName name, - AssemblyBuilderAccess access, - String dir) - { - Contract.Ensures(Contract.Result<AssemblyBuilder>() != null); - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return InternalDefineDynamicAssembly(name, access, dir, - null, null, null, null, - ref stackMark, - null, - SecurityContextSource.CurrentAssembly); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public AssemblyBuilder DefineDynamicAssembly( - AssemblyName name, - AssemblyBuilderAccess access, - Evidence evidence) - { - Contract.Ensures(Contract.Result<AssemblyBuilder>() != null); - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return InternalDefineDynamicAssembly(name, access, null, - evidence, null, null, null, - ref stackMark, - null, - SecurityContextSource.CurrentAssembly); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public AssemblyBuilder DefineDynamicAssembly( - AssemblyName name, - AssemblyBuilderAccess access, - PermissionSet requiredPermissions, - PermissionSet optionalPermissions, - PermissionSet refusedPermissions) - { - Contract.Ensures(Contract.Result<AssemblyBuilder>() != null); - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return InternalDefineDynamicAssembly(name, access, null, null, - requiredPermissions, - optionalPermissions, - refusedPermissions, - ref stackMark, - null, - SecurityContextSource.CurrentAssembly); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of DefineDynamicAssembly which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkId=155570 for more information.")] - public AssemblyBuilder DefineDynamicAssembly( - AssemblyName name, - AssemblyBuilderAccess access, - String dir, - Evidence evidence) - { - Contract.Ensures(Contract.Result<AssemblyBuilder>() != null); - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return InternalDefineDynamicAssembly(name, access, dir, evidence, - null, null, null, ref stackMark, null, SecurityContextSource.CurrentAssembly); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public AssemblyBuilder DefineDynamicAssembly( - AssemblyName name, - AssemblyBuilderAccess access, - String dir, - PermissionSet requiredPermissions, - PermissionSet optionalPermissions, - PermissionSet refusedPermissions) - { - Contract.Ensures(Contract.Result<AssemblyBuilder>() != null); - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return InternalDefineDynamicAssembly(name, access, dir, null, - requiredPermissions, - optionalPermissions, - refusedPermissions, - ref stackMark, - null, - SecurityContextSource.CurrentAssembly); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public AssemblyBuilder DefineDynamicAssembly( - AssemblyName name, - AssemblyBuilderAccess access, - Evidence evidence, - PermissionSet requiredPermissions, - PermissionSet optionalPermissions, - PermissionSet refusedPermissions) - { - Contract.Ensures(Contract.Result<AssemblyBuilder>() != null); - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return InternalDefineDynamicAssembly(name, access, null, - evidence, - requiredPermissions, - optionalPermissions, - refusedPermissions, - ref stackMark, - null, - SecurityContextSource.CurrentAssembly); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. Please see http://go.microsoft.com/fwlink/?LinkId=155570 for more information.")] - public AssemblyBuilder DefineDynamicAssembly( - AssemblyName name, - AssemblyBuilderAccess access, - String dir, - Evidence evidence, - PermissionSet requiredPermissions, - PermissionSet optionalPermissions, - PermissionSet refusedPermissions) - { - Contract.Ensures(Contract.Result<AssemblyBuilder>() != null); - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return InternalDefineDynamicAssembly(name, access, dir, - evidence, - requiredPermissions, - optionalPermissions, - refusedPermissions, - ref stackMark, - null, - SecurityContextSource.CurrentAssembly); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public AssemblyBuilder DefineDynamicAssembly( - AssemblyName name, - AssemblyBuilderAccess access, - String dir, - Evidence evidence, - PermissionSet requiredPermissions, - PermissionSet optionalPermissions, - PermissionSet refusedPermissions, - bool isSynchronized) - { - Contract.Ensures(Contract.Result<AssemblyBuilder>() != null); - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return InternalDefineDynamicAssembly(name, - access, - dir, - evidence, - requiredPermissions, - optionalPermissions, - refusedPermissions, - ref stackMark, - null, - SecurityContextSource.CurrentAssembly); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public AssemblyBuilder DefineDynamicAssembly( - AssemblyName name, - AssemblyBuilderAccess access, - String dir, - Evidence evidence, - PermissionSet requiredPermissions, - PermissionSet optionalPermissions, - PermissionSet refusedPermissions, - bool isSynchronized, - IEnumerable<CustomAttributeBuilder> assemblyAttributes) - { - Contract.Ensures(Contract.Result<AssemblyBuilder>() != null); - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return InternalDefineDynamicAssembly(name, - access, - dir, - evidence, - requiredPermissions, - optionalPermissions, - refusedPermissions, - ref stackMark, - assemblyAttributes, - SecurityContextSource.CurrentAssembly); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - public AssemblyBuilder DefineDynamicAssembly( - AssemblyName name, - AssemblyBuilderAccess access, - String dir, - bool isSynchronized, - IEnumerable<CustomAttributeBuilder> assemblyAttributes) - { - Contract.Ensures(Contract.Result<AssemblyBuilder>() != null); - - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return InternalDefineDynamicAssembly(name, - access, - dir, - null, - null, - null, - null, - ref stackMark, - assemblyAttributes, - SecurityContextSource.CurrentAssembly); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - private AssemblyBuilder InternalDefineDynamicAssembly( - AssemblyName name, - AssemblyBuilderAccess access, - String dir, - Evidence evidence, - PermissionSet requiredPermissions, - PermissionSet optionalPermissions, - PermissionSet refusedPermissions, - ref StackCrawlMark stackMark, - IEnumerable<CustomAttributeBuilder> assemblyAttributes, - SecurityContextSource securityContextSource) - { - return AssemblyBuilder.InternalDefineDynamicAssembly(name, - access, - dir, - evidence, - requiredPermissions, - optionalPermissions, - refusedPermissions, - ref stackMark, - assemblyAttributes, - securityContextSource); - } - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern String nApplyPolicy(AssemblyName an); - - // Return the assembly name that results from applying policy. - [ComVisible(false)] - public String ApplyPolicy(String assemblyName) - { - AssemblyName asmName = new AssemblyName(assemblyName); - - byte[] pk = asmName.GetPublicKeyToken(); - if (pk == null) - pk = asmName.GetPublicKey(); - - // Simply-named assemblies cannot have policy, so for those, - // we simply return the passed-in assembly name. - if ((pk == null) || (pk.Length == 0)) - return assemblyName; - else - return nApplyPolicy(asmName); - } - public ObjectHandle CreateInstance(String assemblyName, String typeName) @@ -1140,437 +720,6 @@ namespace System typeName); } - internal ObjectHandle InternalCreateInstanceWithNoSecurity (string assemblyName, string typeName) { - PermissionSet.s_fullTrust.Assert(); - return CreateInstance(assemblyName, typeName); - } - - public ObjectHandle CreateInstanceFrom(String assemblyFile, - String typeName) - - { - // jit does not check for that, so we should do it ... - if (this == null) - throw new NullReferenceException(); - Contract.EndContractBlock(); - - return Activator.CreateInstanceFrom(assemblyFile, - typeName); - } - - internal ObjectHandle InternalCreateInstanceFromWithNoSecurity (string assemblyName, string typeName) { - PermissionSet.s_fullTrust.Assert(); - return CreateInstanceFrom(assemblyName, typeName); - } - -#if FEATURE_COMINTEROP - // The first parameter should be named assemblyFile, but it was incorrectly named in a previous - // release, and the compatibility police won't let us change the name now. - public ObjectHandle CreateComInstanceFrom(String assemblyName, - String typeName) - - { - if (this == null) - throw new NullReferenceException(); - Contract.EndContractBlock(); - - return Activator.CreateComInstanceFrom(assemblyName, - typeName); - } - - public ObjectHandle CreateComInstanceFrom(String assemblyFile, - String typeName, - byte[] hashValue, - AssemblyHashAlgorithm hashAlgorithm) - - { - if (this == null) - throw new NullReferenceException(); - Contract.EndContractBlock(); - - return Activator.CreateComInstanceFrom(assemblyFile, - typeName, - hashValue, - hashAlgorithm); - } - -#endif // FEATURE_COMINTEROP - - public ObjectHandle CreateInstance(String assemblyName, - String typeName, - Object[] activationAttributes) - - { - // jit does not check for that, so we should do it ... - if (this == null) - throw new NullReferenceException(); - - if (assemblyName == null) - throw new ArgumentNullException(nameof(assemblyName)); - Contract.EndContractBlock(); - - return Activator.CreateInstance(assemblyName, - typeName, - activationAttributes); - } - - public ObjectHandle CreateInstanceFrom(String assemblyFile, - String typeName, - Object[] activationAttributes) - - { - // jit does not check for that, so we should do it ... - if (this == null) - throw new NullReferenceException(); - Contract.EndContractBlock(); - - return Activator.CreateInstanceFrom(assemblyFile, - typeName, - activationAttributes); - } - - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstance which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public ObjectHandle CreateInstance(String assemblyName, - String typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - Object[] args, - CultureInfo culture, - Object[] activationAttributes, - Evidence securityAttributes) - { - // jit does not check for that, so we should do it ... - if (this == null) - throw new NullReferenceException(); - - if (assemblyName == null) - throw new ArgumentNullException(nameof(assemblyName)); - Contract.EndContractBlock(); - -#pragma warning disable 618 - return Activator.CreateInstance(assemblyName, - typeName, - ignoreCase, - bindingAttr, - binder, - args, - culture, - activationAttributes, - securityAttributes); -#pragma warning restore 618 - } - - public ObjectHandle CreateInstance(string assemblyName, - string typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - object[] args, - CultureInfo culture, - object[] activationAttributes) - { - // jit does not check for that, so we should do it ... - if (this == null) - throw new NullReferenceException(); - - if (assemblyName == null) - throw new ArgumentNullException(nameof(assemblyName)); - Contract.EndContractBlock(); - - return Activator.CreateInstance(assemblyName, - typeName, - ignoreCase, - bindingAttr, - binder, - args, - culture, - activationAttributes); - } - - internal ObjectHandle InternalCreateInstanceWithNoSecurity (string assemblyName, - string typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - Object[] args, - CultureInfo culture, - Object[] activationAttributes, - Evidence securityAttributes) - { - PermissionSet.s_fullTrust.Assert(); -#pragma warning disable 618 - return CreateInstance(assemblyName, typeName, ignoreCase, bindingAttr, binder, args, culture, activationAttributes, securityAttributes); -#pragma warning restore 618 - } - - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstanceFrom which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public ObjectHandle CreateInstanceFrom(String assemblyFile, - String typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - Object[] args, - CultureInfo culture, - Object[] activationAttributes, - Evidence securityAttributes) - - { - // jit does not check for that, so we should do it ... - if (this == null) - throw new NullReferenceException(); - Contract.EndContractBlock(); - - return Activator.CreateInstanceFrom(assemblyFile, - typeName, - ignoreCase, - bindingAttr, - binder, - args, - culture, - activationAttributes, - securityAttributes); - } - - public ObjectHandle CreateInstanceFrom(string assemblyFile, - string typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - object[] args, - CultureInfo culture, - object[] activationAttributes) - { - // jit does not check for that, so we should do it ... - if (this == null) - throw new NullReferenceException(); - Contract.EndContractBlock(); - - return Activator.CreateInstanceFrom(assemblyFile, - typeName, - ignoreCase, - bindingAttr, - binder, - args, - culture, - activationAttributes); - } - - internal ObjectHandle InternalCreateInstanceFromWithNoSecurity (string assemblyName, - string typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - Object[] args, - CultureInfo culture, - Object[] activationAttributes, - Evidence securityAttributes) - { - PermissionSet.s_fullTrust.Assert(); -#pragma warning disable 618 - return CreateInstanceFrom(assemblyName, typeName, ignoreCase, bindingAttr, binder, args, culture, activationAttributes, securityAttributes); -#pragma warning restore 618 - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - public Assembly Load(AssemblyName assemblyRef) - { - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return RuntimeAssembly.InternalLoadAssemblyName(assemblyRef, null, null, ref stackMark, true /*thrownOnFileNotFound*/, false, false); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - public Assembly Load(String assemblyString) - { - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return RuntimeAssembly.InternalLoad(assemblyString, null, ref stackMark, false); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - public Assembly Load(byte[] rawAssembly) - { - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return RuntimeAssembly.nLoadImage(rawAssembly, - null, // symbol store - null, // evidence - ref stackMark, - false, - SecurityContextSource.CurrentAssembly); - - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - public Assembly Load(byte[] rawAssembly, - byte[] rawSymbolStore) - { - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return RuntimeAssembly.nLoadImage(rawAssembly, - rawSymbolStore, - null, // evidence - ref stackMark, - false, // fIntrospection - SecurityContextSource.CurrentAssembly); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of Load which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkId=155570 for more information.")] - public Assembly Load(byte[] rawAssembly, - byte[] rawSymbolStore, - Evidence securityEvidence) - { - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return RuntimeAssembly.nLoadImage(rawAssembly, - rawSymbolStore, - securityEvidence, - ref stackMark, - false, // fIntrospection - SecurityContextSource.CurrentAssembly); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of Load which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public Assembly Load(AssemblyName assemblyRef, - Evidence assemblySecurity) - { - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return RuntimeAssembly.InternalLoadAssemblyName(assemblyRef, assemblySecurity, null, ref stackMark, true /*thrownOnFileNotFound*/, false, false); - } - - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of Load which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public Assembly Load(String assemblyString, - Evidence assemblySecurity) - { - StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; - return RuntimeAssembly.InternalLoad(assemblyString, assemblySecurity, ref stackMark, false); - } - - public int ExecuteAssembly(String assemblyFile) - { - return ExecuteAssembly(assemblyFile, (string[])null); - } - - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of ExecuteAssembly which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public int ExecuteAssembly(String assemblyFile, - Evidence assemblySecurity) - { - return ExecuteAssembly(assemblyFile, assemblySecurity, null); - } - - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of ExecuteAssembly which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public int ExecuteAssembly(String assemblyFile, - Evidence assemblySecurity, - String[] args) - { - RuntimeAssembly assembly = (RuntimeAssembly)Assembly.LoadFrom(assemblyFile, assemblySecurity); - - if (args == null) - args = new String[0]; - - return nExecuteAssembly(assembly, args); - } - - public int ExecuteAssembly(string assemblyFile, string[] args) - { - RuntimeAssembly assembly = (RuntimeAssembly)Assembly.LoadFrom(assemblyFile); - - if (args == null) - args = new String[0]; - - return nExecuteAssembly(assembly, args); - } - - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of ExecuteAssembly which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public int ExecuteAssembly(String assemblyFile, - Evidence assemblySecurity, - String[] args, - byte[] hashValue, - AssemblyHashAlgorithm hashAlgorithm) - { - RuntimeAssembly assembly = (RuntimeAssembly)Assembly.LoadFrom(assemblyFile, - assemblySecurity, - hashValue, - hashAlgorithm); - if (args == null) - args = new String[0]; - - return nExecuteAssembly(assembly, args); - } - - public int ExecuteAssembly(string assemblyFile, - string[] args, - byte[] hashValue, - AssemblyHashAlgorithm hashAlgorithm) - { - RuntimeAssembly assembly = (RuntimeAssembly)Assembly.LoadFrom(assemblyFile, - hashValue, - hashAlgorithm); - if (args == null) - args = new String[0]; - - return nExecuteAssembly(assembly, args); - } - - public int ExecuteAssemblyByName(String assemblyName) - { - return ExecuteAssemblyByName(assemblyName, (string[])null); - } - - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of ExecuteAssemblyByName which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public int ExecuteAssemblyByName(String assemblyName, - Evidence assemblySecurity) - { -#pragma warning disable 618 - return ExecuteAssemblyByName(assemblyName, assemblySecurity, null); -#pragma warning restore 618 - } - - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of ExecuteAssemblyByName which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public int ExecuteAssemblyByName(String assemblyName, - Evidence assemblySecurity, - params String[] args) - { - RuntimeAssembly assembly = (RuntimeAssembly)Assembly.Load(assemblyName, assemblySecurity); - - if (args == null) - args = new String[0]; - - return nExecuteAssembly(assembly, args); - } - - public int ExecuteAssemblyByName(string assemblyName, params string[] args) - { - RuntimeAssembly assembly = (RuntimeAssembly)Assembly.Load(assemblyName); - - if (args == null) - args = new String[0]; - - return nExecuteAssembly(assembly, args); - } - - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of ExecuteAssemblyByName which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public int ExecuteAssemblyByName(AssemblyName assemblyName, - Evidence assemblySecurity, - params String[] args) - { - RuntimeAssembly assembly = (RuntimeAssembly)Assembly.Load(assemblyName, assemblySecurity); - - if (args == null) - args = new String[0]; - - return nExecuteAssembly(assembly, args); - } - - public int ExecuteAssemblyByName(AssemblyName assemblyName, params string[] args) - { - RuntimeAssembly assembly = (RuntimeAssembly)Assembly.Load(assemblyName); - - if (args == null) - args = new String[0]; - - return nExecuteAssembly(assembly, args); - } - public static AppDomain CurrentDomain { get { @@ -1579,11 +728,6 @@ namespace System } } - public String FriendlyName - { - get { return nGetFriendlyName(); } - } - public String BaseDirectory { get { @@ -1616,19 +760,6 @@ namespace System return StringBuilderCache.GetStringAndRelease(sb); } - public Assembly[] GetAssemblies() - { - return nGetAssemblies(false /* forIntrospection */); - } - - public Assembly[] ReflectionOnlyGetAssemblies() - { - return nGetAssemblies(true /* forIntrospection */); - } - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern Assembly[] nGetAssemblies(bool forIntrospection); - // this is true when we've removed the handles etc so really can't do anything [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern bool IsUnloadingForcedFinalize(); @@ -1642,38 +773,22 @@ namespace System internal static extern void PublishAnonymouslyHostedDynamicMethodsAssembly(RuntimeAssembly assemblyHandle); public void SetData (string name, object data) { - SetDataHelper(name, data, null); - } - - public void SetData (string name, object data, IPermission permission) - { - if (!name.Equals("LOCATION_URI")) - { - // Only LOCATION_URI can be set using AppDomain.SetData - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SetData_OnlyLocationURI", name)); - } - - SetDataHelper(name, data, permission); - } - - private void SetDataHelper (string name, object data, IPermission permission) - { if (name == null) throw new ArgumentNullException(nameof(name)); Contract.EndContractBlock(); // SetData should only be used to set values that don't already exist. - object[] currentVal; + object currentVal; lock (((ICollection)LocalStore).SyncRoot) { LocalStore.TryGetValue(name, out currentVal); } - if (currentVal != null && currentVal[0] != null) + if (currentVal != null) { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SetData_OnlyOnce")); } lock (((ICollection)LocalStore).SyncRoot) { - LocalStore[name] = new object[] {data, permission}; + LocalStore[name] = data; } } @@ -1687,23 +802,17 @@ namespace System int key = AppDomainSetup.Locate(name); if(key == -1) { -#if FEATURE_LOADER_OPTIMIZATION if(name.Equals(AppDomainSetup.LoaderOptimizationKey)) return FusionStore.LoaderOptimization; else -#endif // FEATURE_LOADER_OPTIMIZATION { - object[] data; + object data; lock (((ICollection)LocalStore).SyncRoot) { LocalStore.TryGetValue(name, out data); } if (data == null) return null; - if (data[1] != null) { - IPermission permission = (IPermission) data[1]; - permission.Demand(); - } - return data[0]; + return data; } } else { @@ -1720,71 +829,16 @@ namespace System } } } - - // The compat flags are set at domain creation time to indicate that the given breaking - // change should not be used in this domain. - // - // After the domain has been created, this Nullable boolean returned by this method should - // always have a value. Code in the runtime uses this to know if it is safe to cache values - // that might change if the compatibility switches have not been set yet. - public Nullable<bool> IsCompatibilitySwitchSet(String value) - { - Nullable<bool> fReturn; - - if (_compatFlagsInitialized == false) - { - fReturn = new Nullable<bool>(); - } - else - { - fReturn = new Nullable<bool>(_compatFlags != null && _compatFlags.ContainsKey(value)); - } - - return fReturn; - } [Obsolete("AppDomain.GetCurrentThreadId has been deprecated because it does not provide a stable Id when managed threads are running on fibers (aka lightweight threads). To get a stable identifier for a managed thread, use the ManagedThreadId property on Thread. http://go.microsoft.com/fwlink/?linkid=14202", false)] [DllImport(Microsoft.Win32.Win32Native.KERNEL32)] public static extern int GetCurrentThreadId(); - internal ApplicationTrust ApplicationTrust - { - get { - if (_applicationTrust == null && _IsFastFullTrustDomain) { - _applicationTrust = new ApplicationTrust(new PermissionSet(PermissionState.Unrestricted)); - } - - return _applicationTrust; - } - } - - public String DynamicDirectory - { - get { - String dyndir = GetDynamicDir(); - if (dyndir != null) - new FileIOPermission( FileIOPermissionAccess.PathDiscovery, dyndir ).Demand(); - - return dyndir; - } - } - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - extern private String GetDynamicDir(); - private AppDomain() { throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_Constructor)); } [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern int _nExecuteAssembly(RuntimeAssembly assembly, String[] args); - internal int nExecuteAssembly(RuntimeAssembly assembly, String[] args) - { - return _nExecuteAssembly(assembly, args); - } - -#if FEATURE_VERSIONING - [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern void nCreateContext(); [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] @@ -1795,12 +849,9 @@ namespace System { nSetupBindingPaths(trustedPlatformAssemblies, platformResourceRoots, appPath, appNiPaths, appLocalWinMD); } -#endif // FEATURE_VERSIONING [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern String nGetFriendlyName(); - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern bool nIsDefaultAppDomainForEvidence(); // support reliability for certain event handlers, if the target // methods also participate in this discipline. If caller passes @@ -1864,7 +915,6 @@ namespace System } } -#if FEATURE_EXCEPTION_NOTIFICATIONS // This is the event managed code can wireup against to be notified // about first chance exceptions. // @@ -1886,7 +936,6 @@ namespace System _firstChanceException -= value; } } -#endif // FEATURE_EXCEPTION_NOTIFICATIONS private void OnAssemblyLoadEvent(RuntimeAssembly LoadedAssembly) { @@ -1990,24 +1039,18 @@ namespace System return null; } - private Dictionary<String, Object[]> LocalStore + private Dictionary<String, Object> LocalStore { get { if (_LocalStore != null) return _LocalStore; else { - _LocalStore = new Dictionary<String, Object[]>(); + _LocalStore = new Dictionary<String, Object>(); return _LocalStore; } } } - // Used to determine if server object context is valid in - // x-domain remoting scenarios. - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - internal static extern bool IsDomainIdValid(Int32 id); - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern void nSetNativeDllSearchDirectories(string paths); @@ -2021,27 +1064,14 @@ namespace System info.SetupDefaults(RuntimeEnvironment.GetModuleFileName(), imageLocationAlreadyNormalized : true); } -#if FEATURE_VERSIONING nCreateContext(); -#endif // FEATURE_VERSIONING -#if FEATURE_LOADER_OPTIMIZATION if (info.LoaderOptimization != LoaderOptimization.NotSpecified || (oldInfo != null && info.LoaderOptimization != oldInfo.LoaderOptimization)) UpdateLoaderOptimization(info.LoaderOptimization); -#endif // This must be the last action taken _FusionStore = info; } - // used to package up evidence, so it can be serialized - // for the call to InternalRemotelySetupRemoteDomain - [Serializable] - private class EvidenceCollection - { - public Evidence ProvidedSecurityInfo; - public Evidence CreatorsSecurityInfo; - } - private static void RunInitializer(AppDomainSetup setup) { if (setup.AppDomainInitializer!=null) @@ -2172,7 +1202,6 @@ namespace System newSetup.ApplicationBase = NormalizePath(propertyValues[i], fullCheck: true); } -#if FEATURE_LOADER_OPTIMIZATION else if(propertyNames[i]=="LOADER_OPTIMIZATION") { if(propertyValues[i]==null) @@ -2187,7 +1216,6 @@ namespace System default: throw new ArgumentException(Environment.GetResourceString("Argument_UnrecognizedLoaderOptimization"), "LOADER_OPTIMIZATION"); } } -#endif // FEATURE_LOADER_OPTIMIZATION else if(propertyNames[i]=="TRUSTED_PLATFORM_ASSEMBLIES" || propertyNames[i]=="PLATFORM_RESOURCE_ROOTS" || propertyNames[i]=="APP_PATHS" || @@ -2197,11 +1225,11 @@ namespace System if(values == null) throw new ArgumentNullException(propertyNames[i]); - ad.SetDataHelper(propertyNames[i], NormalizeAppPaths(values), null); + ad.SetData(propertyNames[i], NormalizeAppPaths(values)); } else if(propertyNames[i]!= null) { - ad.SetDataHelper(propertyNames[i],propertyValues[i],null); // just propagate + ad.SetData(propertyNames[i],propertyValues[i]); // just propagate } } } @@ -2312,22 +1340,6 @@ namespace System } } -#if FEATURE_LOADER_OPTIMIZATION - private void SetupLoaderOptimization(LoaderOptimization policy) - { - if(policy != LoaderOptimization.NotSpecified) { - Debug.Assert(FusionStore.LoaderOptimization == LoaderOptimization.NotSpecified, - "It is illegal to change the Loader optimization on a domain"); - - FusionStore.LoaderOptimization = policy; - UpdateLoaderOptimization(FusionStore.LoaderOptimization); - } - } -#endif - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern IntPtr GetSecurityDescriptor(); - private void SetupDomainSecurity(Evidence appDomainEvidence, IntPtr creatorsSecurityDescriptor, bool publishAppDomain) @@ -2355,10 +1367,8 @@ namespace System private extern void nSetDisableInterfaceCache(); #endif // FEATURE_COMINTEROP -#if FEATURE_LOADER_OPTIMIZATION [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern void UpdateLoaderOptimization(LoaderOptimization optimization); -#endif public AppDomainSetup SetupInformation { @@ -2377,52 +1387,14 @@ namespace System [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void GetGrantSet(AppDomainHandle domain, ObjectHandleOnStack retGrantSet); - public PermissionSet PermissionSet - { - // SecurityCritical because permissions can contain sensitive information such as paths - get - { - PermissionSet grantSet = null; - GetGrantSet(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref grantSet)); - - if (grantSet != null) - { - return grantSet.Copy(); - } - else - { - return new PermissionSet(PermissionState.Unrestricted); - } - } - } - public bool IsFullyTrusted { get { - PermissionSet grantSet = null; - GetGrantSet(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref grantSet)); - - return grantSet == null || grantSet.IsUnrestricted(); - } - } - - public bool IsHomogenous - { - get - { - // Homogenous AppDomains always have an ApplicationTrust associated with them - return _IsFastFullTrustDomain || _applicationTrust != null; + return true; } } - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern void nChangeSecurityPolicy(); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [ReliabilityContract(Consistency.MayCorruptAppDomain, Cer.MayFail)] - internal static extern void nUnload(Int32 domainInternal); - public Object CreateInstanceAndUnwrap(String assemblyName, String typeName) { @@ -2433,269 +1405,16 @@ namespace System return oh.Unwrap(); } // CreateInstanceAndUnwrap - public Object CreateInstanceAndUnwrap(String assemblyName, - String typeName, - Object[] activationAttributes) - { - ObjectHandle oh = CreateInstance(assemblyName, typeName, activationAttributes); - if (oh == null) - return null; - - return oh.Unwrap(); - } // CreateInstanceAndUnwrap - - - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstanceAndUnwrap which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public Object CreateInstanceAndUnwrap(String assemblyName, - String typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - Object[] args, - CultureInfo culture, - Object[] activationAttributes, - Evidence securityAttributes) - { -#pragma warning disable 618 - ObjectHandle oh = CreateInstance(assemblyName, typeName, ignoreCase, bindingAttr, - binder, args, culture, activationAttributes, securityAttributes); -#pragma warning restore 618 - - if (oh == null) - return null; - - return oh.Unwrap(); - } // CreateInstanceAndUnwrap - - public object CreateInstanceAndUnwrap(string assemblyName, - string typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - object[] args, - CultureInfo culture, - object[] activationAttributes) - { - ObjectHandle oh = CreateInstance(assemblyName, - typeName, - ignoreCase, - bindingAttr, - binder, - args, - culture, - activationAttributes); - - if (oh == null) - { - return null; - } - - return oh.Unwrap(); - } - - // The first parameter should be named assemblyFile, but it was incorrectly named in a previous - // release, and the compatibility police won't let us change the name now. - public Object CreateInstanceFromAndUnwrap(String assemblyName, - String typeName) - { - ObjectHandle oh = CreateInstanceFrom(assemblyName, typeName); - if (oh == null) - return null; - - return oh.Unwrap(); - } // CreateInstanceAndUnwrap - - - // The first parameter should be named assemblyFile, but it was incorrectly named in a previous - // release, and the compatibility police won't let us change the name now. - public Object CreateInstanceFromAndUnwrap(String assemblyName, - String typeName, - Object[] activationAttributes) - { - ObjectHandle oh = CreateInstanceFrom(assemblyName, typeName, activationAttributes); - if (oh == null) - return null; - - return oh.Unwrap(); - } // CreateInstanceAndUnwrap - - - // The first parameter should be named assemblyFile, but it was incorrectly named in a previous - // release, and the compatibility police won't let us change the name now. - [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstanceFromAndUnwrap which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")] - public Object CreateInstanceFromAndUnwrap(String assemblyName, - String typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - Object[] args, - CultureInfo culture, - Object[] activationAttributes, - Evidence securityAttributes) - { -#pragma warning disable 618 - ObjectHandle oh = CreateInstanceFrom(assemblyName, typeName, ignoreCase, bindingAttr, - binder, args, culture, activationAttributes, securityAttributes); -#pragma warning restore 618 - - if (oh == null) - return null; - - return oh.Unwrap(); - } // CreateInstanceAndUnwrap - - public object CreateInstanceFromAndUnwrap(string assemblyFile, - string typeName, - bool ignoreCase, - BindingFlags bindingAttr, - Binder binder, - object[] args, - CultureInfo culture, - object[] activationAttributes) - { - ObjectHandle oh = CreateInstanceFrom(assemblyFile, - typeName, - ignoreCase, - bindingAttr, - binder, - args, - culture, - activationAttributes); - if (oh == null) - { - return null; - } - - return oh.Unwrap(); - } - public Int32 Id { - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] get { return GetId(); } } [MethodImplAttribute(MethodImplOptions.InternalCall)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal extern Int32 GetId(); - - internal const Int32 DefaultADID = 1; - - public bool IsDefaultAppDomain() - { - if (GetId()==DefaultADID) - return true; - return false; - } - -#if FEATURE_APPDOMAIN_RESOURCE_MONITORING - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern void nEnableMonitoring(); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern bool nMonitoringIsEnabled(); - - // return -1 if ARM is not supported. - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern Int64 nGetTotalProcessorTime(); - - // return -1 if ARM is not supported. - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern Int64 nGetTotalAllocatedMemorySize(); - - // return -1 if ARM is not supported. - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern Int64 nGetLastSurvivedMemorySize(); - - // return -1 if ARM is not supported. - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern Int64 nGetLastSurvivedProcessMemorySize(); - - public static bool MonitoringIsEnabled - { - get { - return nMonitoringIsEnabled(); - } - - set { - if (value == false) - { - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeTrue")); - } - else - { - nEnableMonitoring(); - } - } - } - // Gets the total processor time for this AppDomain. - // Throws NotSupportedException if ARM is not enabled. - public TimeSpan MonitoringTotalProcessorTime - { - get { - Int64 i64ProcessorTime = nGetTotalProcessorTime(); - if (i64ProcessorTime == -1) - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WithoutARM")); - } - return new TimeSpan(i64ProcessorTime); - } - } - - // Gets the number of bytes allocated in this AppDomain since - // the AppDomain was created. - // Throws NotSupportedException if ARM is not enabled. - public Int64 MonitoringTotalAllocatedMemorySize - { - get { - Int64 i64AllocatedMemory = nGetTotalAllocatedMemorySize(); - if (i64AllocatedMemory == -1) - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WithoutARM")); - } - return i64AllocatedMemory; - } - } - - // Gets the number of bytes survived after the last collection - // that are known to be held by this AppDomain. After a full - // collection this number is accurate and complete. After an - // ephemeral collection this number is potentially incomplete. - // Throws NotSupportedException if ARM is not enabled. - public Int64 MonitoringSurvivedMemorySize - { - get { - Int64 i64LastSurvivedMemory = nGetLastSurvivedMemorySize(); - if (i64LastSurvivedMemory == -1) - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WithoutARM")); - } - return i64LastSurvivedMemory; - } - } - - // Gets the total bytes survived from the last collection. After - // a full collection this number represents the number of the bytes - // being held live in managed heaps. (This number should be close - // to the number obtained from GC.GetTotalMemory for a full collection.) - // After an ephemeral collection this number represents the number - // of bytes being held live in ephemeral generations. - // Throws NotSupportedException if ARM is not enabled. - public static Int64 MonitoringSurvivedProcessMemorySize - { - get { - Int64 i64LastSurvivedProcessMemory = nGetLastSurvivedProcessMemorySize(); - if (i64LastSurvivedProcessMemory == -1) - { - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WithoutARM")); - } - return i64LastSurvivedProcessMemory; - } - } -#endif } /// <summary> diff --git a/src/mscorlib/src/System/AppDomainAttributes.cs b/src/mscorlib/src/System/AppDomainAttributes.cs index 0980b5fe90..960f9c1cac 100644 --- a/src/mscorlib/src/System/AppDomainAttributes.cs +++ b/src/mscorlib/src/System/AppDomainAttributes.cs @@ -14,8 +14,7 @@ namespace System { [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] - public enum LoaderOptimization + internal enum LoaderOptimization { NotSpecified = 0, SingleDomain = 1, @@ -26,23 +25,5 @@ namespace System { [Obsolete("This method has been deprecated. Please use Assembly.Load() instead. http://go.microsoft.com/fwlink/?linkid=14202")] DisallowBindings = 4 } - - [AttributeUsage (AttributeTargets.Method)] - [System.Runtime.InteropServices.ComVisible(true)] - public sealed class LoaderOptimizationAttribute : Attribute - { - internal byte _val; - - public LoaderOptimizationAttribute(byte value) - { - _val = value; - } - public LoaderOptimizationAttribute(LoaderOptimization value) - { - _val = (byte) value; - } - public LoaderOptimization Value - { get {return (LoaderOptimization) _val;} } - } } diff --git a/src/mscorlib/src/System/AppDomainManager.cs b/src/mscorlib/src/System/AppDomainManager.cs index 71bc088d1d..bd2faa0110 100644 --- a/src/mscorlib/src/System/AppDomainManager.cs +++ b/src/mscorlib/src/System/AppDomainManager.cs @@ -15,8 +15,7 @@ namespace System using System.Security; using System.Runtime.InteropServices; - [System.Runtime.InteropServices.ComVisible(true)] - public class AppDomainManager : MarshalByRefObject + internal class AppDomainManager : MarshalByRefObject { public AppDomainManager () {} diff --git a/src/mscorlib/src/System/AppDomainSetup.cs b/src/mscorlib/src/System/AppDomainSetup.cs index fc8a64c192..0d19ad237f 100644 --- a/src/mscorlib/src/System/AppDomainSetup.cs +++ b/src/mscorlib/src/System/AppDomainSetup.cs @@ -26,10 +26,7 @@ namespace System using System.Collections.Generic; [Serializable] - [ClassInterface(ClassInterfaceType.None)] - [System.Runtime.InteropServices.ComVisible(true)] - public sealed class AppDomainSetup : - IAppDomainSetup + internal sealed class AppDomainSetup { [Serializable] internal enum LoaderInformation @@ -55,7 +52,7 @@ namespace System ConfigurationBytesValue = 15, // LOADER_CONFIGURATION_BYTES LoaderMaximum = 18 // LOADER_MAXIMUM } - + // Constants from fusionsetup.h. private const string LOADER_OPTIMIZATION = "LOADER_OPTIMIZATION"; private const string CONFIGURATION_EXTENSION = ".config"; @@ -439,22 +436,6 @@ namespace System return path; } - private bool IsFilePath(String path) - { -#if !PLATFORM_UNIX - return (path[1] == ':') || ( (path[0] == '\\') && (path[1] == '\\') ); -#else - return (path[0] == '/'); -#endif // !PLATFORM_UNIX - } - - internal static String ApplicationBaseKey - { - get { - return ACTAG_APP_BASE_URL; - } - } - public String ConfigurationFile { get { @@ -466,22 +447,6 @@ namespace System } } - // Used by the ResourceManager internally. This must not do any - // security checks to avoid infinite loops. - internal String ConfigurationFileInternal - { - get { - return NormalizePath(Value[(int) LoaderInformation.ConfigurationFileValue], true); - } - } - - internal static String ConfigurationFileKey - { - get { - return ACTAG_APP_CONFIG_FILE; - } - } - public byte[] GetConfigurationBytes() { if (_ConfigurationBytes == null) @@ -490,18 +455,6 @@ namespace System return (byte[]) _ConfigurationBytes.Clone(); } - public void SetConfigurationBytes(byte[] value) - { - _ConfigurationBytes = value; - } - - private static String ConfigurationBytesKey - { - get { - return ACTAG_APP_CONFIG_BLOB; - } - } - // only needed by AppDomain.Setup(). Not really needed by users. internal Dictionary<string, object> GetCompatibilityFlags() { @@ -543,105 +496,6 @@ namespace System } } - internal bool CheckedForTargetFrameworkName - { - get { return _CheckedForTargetFrameworkName; } - set { _CheckedForTargetFrameworkName = value; } - } - - public String DynamicBase - { - get { - return VerifyDir(Value[(int) LoaderInformation.DynamicBaseValue], true); - } - - set { - if (value == null) - Value[(int) LoaderInformation.DynamicBaseValue] = null; - else { - if(ApplicationName == null) - throw new MemberAccessException(Environment.GetResourceString("AppDomain_RequireApplicationName")); - - StringBuilder s = new StringBuilder( NormalizePath(value, false) ); - s.Append('\\'); - string h = ParseNumbers.IntToString(ApplicationName.GetLegacyNonRandomizedHashCode(), - 16, 8, '0', ParseNumbers.PrintAsI4); - s.Append(h); - - Value[(int) LoaderInformation.DynamicBaseValue] = s.ToString(); - } - } - } - - internal static String DynamicBaseKey - { - get { - return ACTAG_APP_DYNAMIC_BASE; - } - } - - public bool DisallowPublisherPolicy - { - get - { - return (Value[(int) LoaderInformation.DisallowPublisherPolicyValue] != null); - } - set - { - if (value) - Value[(int) LoaderInformation.DisallowPublisherPolicyValue]="true"; - else - Value[(int) LoaderInformation.DisallowPublisherPolicyValue]=null; - } - } - - - public bool DisallowBindingRedirects - { - get - { - return (Value[(int) LoaderInformation.DisallowBindingRedirectsValue] != null); - } - set - { - if (value) - Value[(int) LoaderInformation.DisallowBindingRedirectsValue] = "true"; - else - Value[(int) LoaderInformation.DisallowBindingRedirectsValue] = null; - } - } - - public bool DisallowCodeDownload - { - get - { - return (Value[(int) LoaderInformation.DisallowCodeDownloadValue] != null); - } - set - { - if (value) - Value[(int) LoaderInformation.DisallowCodeDownloadValue] = "true"; - else - Value[(int) LoaderInformation.DisallowCodeDownloadValue] = null; - } - } - - - public bool DisallowApplicationBaseProbing - { - get - { - return (Value[(int) LoaderInformation.DisallowAppBaseProbingValue] != null); - } - set - { - if (value) - Value[(int) LoaderInformation.DisallowAppBaseProbingValue] = "true"; - else - Value[(int) LoaderInformation.DisallowAppBaseProbingValue] = null; - } - } - private String VerifyDir(String dir, bool normalize) { if (dir != null) { @@ -656,93 +510,6 @@ namespace System return dir; } - private void VerifyDirList(String dirs) - { - if (dirs != null) { - String[] dirArray = dirs.Split(';'); - int len = dirArray.Length; - - for (int i = 0; i < len; i++) - VerifyDir(dirArray[i], true); - } - } - - internal String DeveloperPath - { - get { - String dirs = Value[(int) LoaderInformation.DevPathValue]; - VerifyDirList(dirs); - return dirs; - } - - set { - if(value == null) - Value[(int) LoaderInformation.DevPathValue] = null; - else { - String[] directories = value.Split(';'); - int size = directories.Length; - StringBuilder newPath = StringBuilderCache.Acquire(); - bool fDelimiter = false; - - for(int i = 0; i < size; i++) { - if(directories[i].Length != 0) { - if(fDelimiter) - newPath.Append(";"); - else - fDelimiter = true; - - newPath.Append(Path.GetFullPath(directories[i])); - } - } - - String newString = StringBuilderCache.GetStringAndRelease(newPath); - if (newString.Length == 0) - Value[(int) LoaderInformation.DevPathValue] = null; - else - Value[(int) LoaderInformation.DevPathValue] = newString; - } - } - } - - internal static String DisallowPublisherPolicyKey - { - get - { - return ACTAG_DISALLOW_APPLYPUBLISHERPOLICY; - } - } - - internal static String DisallowCodeDownloadKey - { - get - { - return ACTAG_CODE_DOWNLOAD_DISABLED; - } - } - - internal static String DisallowBindingRedirectsKey - { - get - { - return ACTAG_DISALLOW_APP_BINDING_REDIRECTS; - } - } - - internal static String DeveloperPathKey - { - get { - return ACTAG_DEV_PATH; - } - } - - internal static String DisallowAppBaseProbingKey - { - get - { - return ACTAG_DISALLOW_APP_BASE_PROBING; - } - } - public String ApplicationName { get { @@ -754,13 +521,6 @@ namespace System } } - internal static String ApplicationNameKey - { - get { - return ACTAG_APP_NAME; - } - } - [XmlIgnoreMember] public AppDomainInitializer AppDomainInitializer { @@ -786,7 +546,7 @@ namespace System internal ApplicationTrust InternalGetApplicationTrust() { if (_ApplicationTrust == null) return null; - ApplicationTrust grantSet = new ApplicationTrust(NamedPermissionSet.GetBuiltInSet(_ApplicationTrust)); + ApplicationTrust grantSet = new ApplicationTrust(); return grantSet; } @@ -804,115 +564,6 @@ namespace System } } - public String PrivateBinPath - { - get { - String dirs = Value[(int) LoaderInformation.PrivateBinPathValue]; - VerifyDirList(dirs); - return dirs; - } - - set { - Value[(int) LoaderInformation.PrivateBinPathValue] = value; - } - } - - internal static String PrivateBinPathKey - { - get { - return ACTAG_APP_PRIVATE_BINPATH; - } - } - - public String PrivateBinPathProbe - { - get { - return Value[(int) LoaderInformation.PrivateBinPathProbeValue]; - } - - set { - Value[(int) LoaderInformation.PrivateBinPathProbeValue] = value; - } - } - - internal static String PrivateBinPathProbeKey - { - get { - return ACTAG_BINPATH_PROBE_ONLY; - } - } - - public String ShadowCopyDirectories - { - get { - String dirs = Value[(int) LoaderInformation.ShadowCopyDirectoriesValue]; - VerifyDirList(dirs); - return dirs; - } - - set { - Value[(int) LoaderInformation.ShadowCopyDirectoriesValue] = value; - } - } - - internal static String ShadowCopyDirectoriesKey - { - get { - return ACTAG_APP_SHADOW_COPY_DIRS; - } - } - - public String ShadowCopyFiles - { - get { - return Value[(int) LoaderInformation.ShadowCopyFilesValue]; - } - - set { - if((value != null) && - (String.Compare(value, "true", StringComparison.OrdinalIgnoreCase) == 0)) - Value[(int) LoaderInformation.ShadowCopyFilesValue] = value; - else - Value[(int) LoaderInformation.ShadowCopyFilesValue] = null; - } - } - - internal static String ShadowCopyFilesKey - { - get { - return ACTAG_FORCE_CACHE_INSTALL; - } - } - - public String CachePath - { - get { - return VerifyDir(Value[(int) LoaderInformation.CachePathValue], false); - } - - set { - Value[(int) LoaderInformation.CachePathValue] = NormalizePath(value, false); - } - } - - internal static String CachePathKey - { - get { - return ACTAG_APP_CACHE_BASE; - } - } - - public String LicenseFile - { - get { - return VerifyDir(Value[(int) LoaderInformation.LicenseFileValue], true); - } - - set { - Value[(int) LoaderInformation.LicenseFileValue] = value; - } - } - public LoaderOptimization LoaderOptimization { get { @@ -938,34 +589,6 @@ namespace System } } - internal static String PrivateBinPathEnvironmentVariable - { - get { - return APPENV_RELATIVEPATH; - } - } - - internal static string RuntimeConfigurationFile - { - get { - return MACHINE_CONFIGURATION_FILE; - } - } - - internal static string MachineConfigKey - { - get { - return ACTAG_MACHINE_CONFIG; - } - } - - internal static string HostBindingKey - { - get { - return ACTAG_HOST_CONFIG_FILE; - } - } - static internal int Locate(String s) { if(String.IsNullOrEmpty(s)) diff --git a/src/mscorlib/src/System/AppDomainUnloadedException.cs b/src/mscorlib/src/System/AppDomainUnloadedException.cs index 8ba37dc4c5..30bee7c7de 100644 --- a/src/mscorlib/src/System/AppDomainUnloadedException.cs +++ b/src/mscorlib/src/System/AppDomainUnloadedException.cs @@ -15,23 +15,12 @@ namespace System { using System.Runtime.Serialization; - [System.Runtime.InteropServices.ComVisible(true)] [Serializable] - public class AppDomainUnloadedException : SystemException { + internal class AppDomainUnloadedException : SystemException { public AppDomainUnloadedException() : base(Environment.GetResourceString("Arg_AppDomainUnloadedException")) { SetErrorCode(__HResults.COR_E_APPDOMAINUNLOADED); } - - public AppDomainUnloadedException(String message) - : base(message) { - SetErrorCode(__HResults.COR_E_APPDOMAINUNLOADED); - } - - public AppDomainUnloadedException(String message, Exception innerException) - : base(message, innerException) { - SetErrorCode(__HResults.COR_E_APPDOMAINUNLOADED); - } // //This constructor is required for serialization. diff --git a/src/mscorlib/src/System/ApplicationException.cs b/src/mscorlib/src/System/ApplicationException.cs index c56746fae0..900feb57f9 100644 --- a/src/mscorlib/src/System/ApplicationException.cs +++ b/src/mscorlib/src/System/ApplicationException.cs @@ -12,9 +12,10 @@ ** =============================================================================*/ -namespace System { - - using System.Runtime.Serialization; +using System.Runtime.Serialization; + +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 @@ -22,35 +23,34 @@ namespace System { // ApplicationException extends but adds no new functionality to // RecoverableException. // - [System.Runtime.InteropServices.ComVisible(true)] [Serializable] - public class ApplicationException : Exception { - + 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. - public ApplicationException() - : base(Environment.GetResourceString("Arg_ApplicationException")) { - SetErrorCode(__HResults.COR_E_APPLICATION); + public ApplicationException() + : base(SR.Arg_ApplicationException) + { + HResult = __HResults.COR_E_APPLICATION; } - + // 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. // - public ApplicationException(String message) - : base(message) { - SetErrorCode(__HResults.COR_E_APPLICATION); - } - - public ApplicationException(String message, Exception innerException) - : base(message, innerException) { - SetErrorCode(__HResults.COR_E_APPLICATION); + public ApplicationException(String message) + : base(message) + { + HResult = __HResults.COR_E_APPLICATION; } - protected ApplicationException(SerializationInfo info, StreamingContext context) : base(info, context) { + public ApplicationException(String message, Exception innerException) + : base(message, innerException) + { + HResult = __HResults.COR_E_APPLICATION; } + protected ApplicationException(SerializationInfo info, StreamingContext context) : base(info, context) { } } - } diff --git a/src/mscorlib/src/System/ApplicationId.cs b/src/mscorlib/src/System/ApplicationId.cs deleted file mode 100644 index 93fc37dd99..0000000000 --- a/src/mscorlib/src/System/ApplicationId.cs +++ /dev/null @@ -1,141 +0,0 @@ -// 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 class identifies a deployment or manifest identity. -// - -namespace System { - using System.Reflection; - using System.Security; - using System.Security.Policy; - using System.Security.Util; - using System.Text; - using System.Diagnostics.Contracts; - - [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] - public sealed class ApplicationId { - private string m_name; - private Version m_version; - private string m_processorArchitecture; - private string m_culture; - internal byte[] m_publicKeyToken; - - internal ApplicationId () {} - - // - // Public. - // - - public ApplicationId (byte[] publicKeyToken, string name, Version version, string processorArchitecture, string culture) { - if (name == null) - throw new ArgumentNullException(nameof(name)); - if (name.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyApplicationName")); - if (version == null) - throw new ArgumentNullException(nameof(version)); - if (publicKeyToken == null) - throw new ArgumentNullException(nameof(publicKeyToken)); - Contract.EndContractBlock(); - - m_publicKeyToken = new byte[publicKeyToken.Length]; - Array.Copy(publicKeyToken, 0, m_publicKeyToken, 0, publicKeyToken.Length); - m_name = name; - m_version = version; - m_processorArchitecture = processorArchitecture; - m_culture = culture; - } - - public byte[] PublicKeyToken { - get { - byte[] publicKeyToken = new byte[m_publicKeyToken.Length]; - Array.Copy(m_publicKeyToken, 0, publicKeyToken, 0, m_publicKeyToken.Length); - return publicKeyToken; - } - } - - public string Name { - get { - return m_name; - } - } - - public Version Version { - get { - return m_version; - } - } - - public string ProcessorArchitecture { - get { - return m_processorArchitecture; - } - } - - public string Culture { - get { - return m_culture; - } - } - - public ApplicationId Copy () { - return new ApplicationId(m_publicKeyToken, m_name, m_version, m_processorArchitecture, m_culture); - } - - public override string ToString () { - StringBuilder sb = StringBuilderCache.Acquire(); - sb.Append(this.m_name); - if (m_culture != null) { - sb.Append(", culture=\""); - sb.Append(m_culture); - sb.Append("\""); - } - sb.Append(", version=\""); - sb.Append(m_version.ToString()); - sb.Append("\""); - if (m_publicKeyToken != null) { - sb.Append(", publicKeyToken=\""); - sb.Append(Hex.EncodeHexString(m_publicKeyToken)); - sb.Append("\""); - } - if (m_processorArchitecture != null) { - sb.Append(", processorArchitecture =\""); - sb.Append(this.m_processorArchitecture); - sb.Append("\""); - } - return StringBuilderCache.GetStringAndRelease(sb); - } - - public override bool Equals (Object o) { - ApplicationId other = (o as ApplicationId); - if (other == null) - return false; - - if (!(Equals(this.m_name, other.m_name) && - Equals(this.m_version, other.m_version) && - Equals(this.m_processorArchitecture, other.m_processorArchitecture) && - Equals(this.m_culture, other.m_culture))) - return false; - - if (this.m_publicKeyToken.Length != other.m_publicKeyToken.Length) - return false; - - for (int i = 0; i < this.m_publicKeyToken.Length; ++i) { - if (this.m_publicKeyToken[i] != other.m_publicKeyToken[i]) - return false; - } - - return true; - } - - public override int GetHashCode() { - // Note: purposely skipping publicKeyToken, processor architecture and culture as they - // are less likely to make things not equal than name and version. - return m_name.GetHashCode() ^ m_version.GetHashCode(); - } - } -} diff --git a/src/mscorlib/src/System/ArgIterator.cs b/src/mscorlib/src/System/ArgIterator.cs index c5bc379505..83a60b95e1 100644 --- a/src/mscorlib/src/System/ArgIterator.cs +++ b/src/mscorlib/src/System/ArgIterator.cs @@ -16,6 +16,19 @@ namespace System { [StructLayout(LayoutKind.Sequential)] public struct ArgIterator { + private IntPtr ArgCookie; // Cookie from the EE. + + // The SigPointer structure consists of the following members. (Note: this is an inline native SigPointer data type) + private IntPtr sigPtr; // Pointer to remaining signature. + private IntPtr sigPtrLen; // Remaining length of the pointer + + // Note, sigPtrLen is actually a DWORD, but on 64bit systems this structure becomes + // 8-byte aligned, which requires us to pad it. + + private IntPtr ArgPtr; // Pointer to remaining args. + private int RemainingArgs; // # of remaining args. + +#if VARARGS_ENABLED //The JIT doesn't support Varargs calling convention. [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern ArgIterator(IntPtr arglist); @@ -34,7 +47,6 @@ namespace System { // This is much like the C va_start macro [CLSCompliant(false)] - public unsafe ArgIterator(RuntimeArgumentHandle arglist, void* ptr) : this(arglist.Value, ptr) { } @@ -121,17 +133,54 @@ namespace System { { throw new NotSupportedException(Environment.GetResourceString("NotSupported_NYI")); } +#else + public ArgIterator(RuntimeArgumentHandle arglist) + { + throw new PlatformNotSupportedException(); //The JIT requires work to enable ArgIterator see: https://github.com/dotnet/coreclr/issues/9204. + } - private IntPtr ArgCookie; // Cookie from the EE. + [CLSCompliant(false)] + public unsafe ArgIterator(RuntimeArgumentHandle arglist, void* ptr) + { + throw new PlatformNotSupportedException(); //The JIT requires work to enable ArgIterator see: https://github.com/dotnet/coreclr/issues/9204. + } - // The SigPointer structure consists of the following members. (Note: this is an inline native SigPointer data type) - private IntPtr sigPtr; // Pointer to remaining signature. - private IntPtr sigPtrLen; // Remaining length of the pointer + public void End() + { + throw new PlatformNotSupportedException(); //The JIT requires work to enable ArgIterator see: https://github.com/dotnet/coreclr/issues/9204. + } - // Note, sigPtrLen is actually a DWORD, but on 64bit systems this structure becomes - // 8-byte aligned, which requires us to pad it. - - private IntPtr ArgPtr; // Pointer to remaining args. - private int RemainingArgs; // # of remaining args. + public override bool Equals(Object o) + { + throw new PlatformNotSupportedException(); //The JIT requires work to enable ArgIterator see: https://github.com/dotnet/coreclr/issues/9204. + } + + public override int GetHashCode() + { + throw new PlatformNotSupportedException(); //The JIT requires work to enable ArgIterator see: https://github.com/dotnet/coreclr/issues/9204. + } + + [System.CLSCompliantAttribute(false)] + public System.TypedReference GetNextArg() + { + throw new PlatformNotSupportedException(); //The JIT requires work to enable ArgIterator see: https://github.com/dotnet/coreclr/issues/9204. + } + + [System.CLSCompliantAttribute(false)] + public System.TypedReference GetNextArg(System.RuntimeTypeHandle rth) + { + throw new PlatformNotSupportedException(); //The JIT requires work to enable ArgIterator see: https://github.com/dotnet/coreclr/issues/9204. + } + + public unsafe System.RuntimeTypeHandle GetNextArgType() + { + throw new PlatformNotSupportedException(); //The JIT requires work to enable ArgIterator see: https://github.com/dotnet/coreclr/issues/9204. + } + + public int GetRemainingCount() + { + throw new PlatformNotSupportedException(); //The JIT requires work to enable ArgIterator see: https://github.com/dotnet/coreclr/issues/9204. + } +#endif //VARARGS_ENABLED } } diff --git a/src/mscorlib/src/System/ArgumentException.cs b/src/mscorlib/src/System/ArgumentException.cs index f37b7690a8..fe054a9aa0 100644 --- a/src/mscorlib/src/System/ArgumentException.cs +++ b/src/mscorlib/src/System/ArgumentException.cs @@ -11,84 +11,87 @@ ** =============================================================================*/ -namespace System { - - using System; - using System.Runtime.Remoting; - using System.Runtime.Serialization; - using System.Globalization; - using System.Security.Permissions; - using System.Diagnostics.Contracts; +using System.Globalization; +using System.Runtime.Serialization; + +namespace System +{ // 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. // - [System.Runtime.InteropServices.ComVisible(true)] [Serializable] - public class ArgumentException : SystemException, ISerializable { - private String m_paramName; - + public class ArgumentException : SystemException, ISerializable + { + private String _paramName; + // Creates a new ArgumentException with its message // string set to the empty string. - public ArgumentException() - : base(Environment.GetResourceString("Arg_ArgumentException")) { - SetErrorCode(__HResults.COR_E_ARGUMENT); + public ArgumentException() + : base(SR.Arg_ArgumentException) + { + HResult = __HResults.COR_E_ARGUMENT; } - + // Creates a new ArgumentException with its message // string set to message. // - public ArgumentException(String message) - : base(message) { - SetErrorCode(__HResults.COR_E_ARGUMENT); + public ArgumentException(String message) + : base(message) + { + HResult = __HResults.COR_E_ARGUMENT; } - - public ArgumentException(String message, Exception innerException) - : base(message, innerException) { - SetErrorCode(__HResults.COR_E_ARGUMENT); + + public ArgumentException(String message, Exception innerException) + : base(message, innerException) + { + HResult = __HResults.COR_E_ARGUMENT; } - public ArgumentException(String message, String paramName, Exception innerException) - : base(message, innerException) { - m_paramName = paramName; - SetErrorCode(__HResults.COR_E_ARGUMENT); + public ArgumentException(String message, String paramName, Exception innerException) + : base(message, innerException) + { + _paramName = paramName; + HResult = __HResults.COR_E_ARGUMENT; } - - public ArgumentException (String message, String paramName) - - : base (message) { - m_paramName = paramName; - SetErrorCode(__HResults.COR_E_ARGUMENT); + + public ArgumentException(String message, String paramName) + : base(message) + { + _paramName = paramName; + HResult = __HResults.COR_E_ARGUMENT; } - protected ArgumentException(SerializationInfo info, StreamingContext context) : base(info, context) { - m_paramName = info.GetString("ParamName"); + protected ArgumentException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + _paramName = info.GetString("ParamName"); } - + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + info.AddValue("ParamName", _paramName, typeof(String)); + } + public override String Message { - get { + get + { String s = base.Message; - if (!String.IsNullOrEmpty(m_paramName)) { - String resourceString = Environment.GetResourceString("Arg_ParamName_Name", m_paramName); + if (!String.IsNullOrEmpty(_paramName)) + { + String resourceString = SR.Format(SR.Arg_ParamName_Name, _paramName); return s + Environment.NewLine + resourceString; } else return s; } } - - public virtual String ParamName { - get { return m_paramName; } - } - - public override void GetObjectData(SerializationInfo info, StreamingContext context) { - if (info==null) { - throw new ArgumentNullException(nameof(info)); - } - Contract.EndContractBlock(); - base.GetObjectData(info, context); - info.AddValue("ParamName", m_paramName, typeof(String)); + + public virtual String ParamName + { + get { return _paramName; } } } } diff --git a/src/mscorlib/src/System/ArgumentNullException.cs b/src/mscorlib/src/System/ArgumentNullException.cs index 661ebd29af..3a86223ccf 100644 --- a/src/mscorlib/src/System/ArgumentNullException.cs +++ b/src/mscorlib/src/System/ArgumentNullException.cs @@ -11,44 +11,43 @@ ** =============================================================================*/ -namespace System { - - using System; - using System.Runtime.Serialization; - using System.Runtime.Remoting; - using System.Security.Permissions; - +using System.Runtime.Serialization; + +namespace System +{ // The ArgumentException is thrown when an argument // is null when it shouldn't be. // - [System.Runtime.InteropServices.ComVisible(true)] [Serializable] public class ArgumentNullException : ArgumentException { // Creates a new ArgumentNullException with its message // string set to a default message explaining an argument was null. - public ArgumentNullException() - : base(Environment.GetResourceString("ArgumentNull_Generic")) { - // Use E_POINTER - COM used that for null pointers. Description is "invalid pointer" - SetErrorCode(__HResults.E_POINTER); + public ArgumentNullException() + : base(SR.ArgumentNull_Generic) + { + // Use E_POINTER - COM used that for null pointers. Description is "invalid pointer" + HResult = __HResults.E_POINTER; } - public ArgumentNullException(String paramName) - : base(Environment.GetResourceString("ArgumentNull_Generic"), paramName) { - SetErrorCode(__HResults.E_POINTER); + public ArgumentNullException(String paramName) + : base(SR.ArgumentNull_Generic, paramName) + { + HResult = __HResults.E_POINTER; } - public ArgumentNullException(String message, Exception innerException) - : base(message, innerException) { - SetErrorCode(__HResults.E_POINTER); - } - - public ArgumentNullException(String paramName, String message) - : base(message, paramName) { - SetErrorCode(__HResults.E_POINTER); + public ArgumentNullException(String message, Exception innerException) + : base(message, innerException) + { + HResult = __HResults.E_POINTER; } - protected ArgumentNullException(SerializationInfo info, StreamingContext context) : base(info, context) { + public ArgumentNullException(String paramName, String message) + : base(message, paramName) + { + HResult = __HResults.E_POINTER; } + + protected ArgumentNullException(SerializationInfo info, StreamingContext context) : base(info, context) { } } } diff --git a/src/mscorlib/src/System/ArgumentOutOfRangeException.cs b/src/mscorlib/src/System/ArgumentOutOfRangeException.cs index 78a90db34e..59a8434089 100644 --- a/src/mscorlib/src/System/ArgumentOutOfRangeException.cs +++ b/src/mscorlib/src/System/ArgumentOutOfRangeException.cs @@ -17,12 +17,10 @@ namespace System { using System.Runtime.Remoting; using System.Runtime.Serialization; using System.Globalization; - using System.Security.Permissions; using System.Diagnostics.Contracts; // The ArgumentOutOfRangeException is thrown when an argument // is outside the legal range for that argument. - [System.Runtime.InteropServices.ComVisible(true)] [Serializable] public class ArgumentOutOfRangeException : ArgumentException, ISerializable { diff --git a/src/mscorlib/src/System/ArithmeticException.cs b/src/mscorlib/src/System/ArithmeticException.cs index f5360939cc..081ba454f5 100644 --- a/src/mscorlib/src/System/ArithmeticException.cs +++ b/src/mscorlib/src/System/ArithmeticException.cs @@ -11,42 +11,41 @@ ** =============================================================================*/ -namespace System { - - using System; - using System.Runtime.Serialization; +using System.Runtime.Serialization; + +namespace System +{ // The ArithmeticException is thrown when overflow or underflow // occurs. // - [System.Runtime.InteropServices.ComVisible(true)] [Serializable] 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. - public ArithmeticException() - : base(Environment.GetResourceString("Arg_ArithmeticException")) { - SetErrorCode(__HResults.COR_E_ARITHMETIC); + public ArithmeticException() + : base(SR.Arg_ArithmeticException) + { + HResult = __HResults.COR_E_ARITHMETIC; } - + // 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. // - public ArithmeticException(String message) - : base(message) { - SetErrorCode(__HResults.COR_E_ARITHMETIC); - } - - public ArithmeticException(String message, Exception innerException) - : base(message, innerException) { - SetErrorCode(__HResults.COR_E_ARITHMETIC); + public ArithmeticException(String message) + : base(message) + { + HResult = __HResults.COR_E_ARITHMETIC; } - protected ArithmeticException(SerializationInfo info, StreamingContext context) : base(info, context) { + public ArithmeticException(String message, Exception innerException) + : base(message, innerException) + { + HResult = __HResults.COR_E_ARITHMETIC; } + protected ArithmeticException(SerializationInfo info, StreamingContext context) : base(info, context) { } } - } diff --git a/src/mscorlib/src/System/Array.cs b/src/mscorlib/src/System/Array.cs index 7bb6ebbdd3..23989f30fb 100644 --- a/src/mscorlib/src/System/Array.cs +++ b/src/mscorlib/src/System/Array.cs @@ -20,13 +20,11 @@ namespace System { using System.Runtime.Versioning; using System.Security; using System.Diagnostics; - using System.Security.Permissions; using System.Diagnostics.Contracts; // Note that we make a T[] (single-dimensional w/ zero as the lower bound) implement both // IList<U> and IReadOnlyList<U>, where T : U dynamically. See the SZArrayHelper class for details. [Serializable] - [ComVisible(true)] public abstract class Array : ICloneable, IList, IStructuralComparable, IStructuralEquatable { // This ctor exists solely to prevent C# from generating a protected .ctor that violates the surface area. I really want this to be a @@ -43,7 +41,6 @@ namespace System { return new ReadOnlyCollection<T>(array); } - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static void Resize<T>(ref T[] array, int newSize) { if (newSize < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.newSize, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); @@ -154,7 +151,7 @@ namespace System { if (lengths[i] < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.lengths, i, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); - fixed (int* pLengths = lengths) + fixed (int* pLengths = &lengths[0]) return InternalCreate((void*)t.TypeHandle.Value,lengths.Length,pLengths,null); } @@ -211,8 +208,8 @@ namespace System { if (lengths[i] < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.lengths, i, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); - fixed (int* pLengths = lengths) - fixed(int* pLowerBounds = lowerBounds) + fixed (int* pLengths = &lengths[0]) + fixed(int* pLowerBounds = &lowerBounds[0]) return InternalCreate((void*)t.TypeHandle.Value,lengths.Length,pLengths,pLowerBounds); } @@ -224,25 +221,9 @@ namespace System { return CreateInstance(elementType, length); } - internal static Array UnsafeCreateInstance(Type elementType, int length1, int length2) - { - return CreateInstance(elementType, length1, length2); - } - - internal static Array UnsafeCreateInstance(Type elementType, params int[] lengths) - { - return CreateInstance(elementType, lengths); - } - - internal static Array UnsafeCreateInstance(Type elementType, int[] lengths, int[] lowerBounds) - { - return CreateInstance(elementType, lengths, lowerBounds); - } - // Copies length elements from sourceArray, starting at index 0, to // destinationArray, starting at index 0. // - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Copy(Array sourceArray, Array destinationArray, int length) { if (sourceArray == null) @@ -263,7 +244,6 @@ namespace System { // Copies length elements from sourceArray, starting at sourceIndex, to // destinationArray, starting at destinationIndex. // - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length) { Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length, false); @@ -273,7 +253,6 @@ namespace System { // instance & might fail when called from within a CER, or if the // reliable flag is true, it will either always succeed or always // throw an exception with no side effects. - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length, bool reliable); @@ -282,13 +261,11 @@ namespace System { // compatible array types based on the array element type - this // method does not support casting, boxing, or primitive widening. // It will up-cast, assuming the array types are correct. - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static void ConstrainedCopy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length) { Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length, true); } - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Copy(Array sourceArray, Array destinationArray, long length) { if (length > Int32.MaxValue || length < Int32.MinValue) @@ -297,7 +274,6 @@ namespace System { Array.Copy(sourceArray, destinationArray, (int) length); } - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Copy(Array sourceArray, long sourceIndex, Array destinationArray, long destinationIndex, long length) { if (sourceIndex > Int32.MaxValue || sourceIndex < Int32.MinValue) @@ -315,7 +291,6 @@ namespace System { // at index. // [MethodImplAttribute(MethodImplOptions.InternalCall)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public static extern void Clear(Array array, int index, int length); // The various Get values... @@ -328,7 +303,7 @@ namespace System { Contract.EndContractBlock(); TypedReference elemref = new TypedReference(); - fixed(int* pIndices = indices) + fixed(int* pIndices = &indices[0]) InternalGetReference(&elemref, indices.Length, pIndices); return TypedReference.InternalToObject(&elemref); } @@ -375,7 +350,6 @@ namespace System { return TypedReference.InternalToObject(&elemref); } - [ComVisible(false)] public Object GetValue(long index) { if (index > Int32.MaxValue || index < Int32.MinValue) @@ -385,7 +359,6 @@ namespace System { return this.GetValue((int) index); } - [ComVisible(false)] public Object GetValue(long index1, long index2) { if (index1 > Int32.MaxValue || index1 < Int32.MinValue) @@ -397,7 +370,6 @@ namespace System { return this.GetValue((int) index1, (int) index2); } - [ComVisible(false)] public Object GetValue(long index1, long index2, long index3) { if (index1 > Int32.MaxValue || index1 < Int32.MinValue) @@ -411,7 +383,6 @@ namespace System { return this.GetValue((int) index1, (int) index2, (int) index3); } - [ComVisible(false)] public Object GetValue(params long[] indices) { if (indices == null) @@ -485,12 +456,11 @@ namespace System { Contract.EndContractBlock(); TypedReference elemref = new TypedReference(); - fixed(int* pIndices = indices) + fixed(int* pIndices = &indices[0]) InternalGetReference(&elemref, indices.Length, pIndices); InternalSetValue(&elemref,value); } - [ComVisible(false)] public void SetValue(Object value, long index) { if (index > Int32.MaxValue || index < Int32.MinValue) @@ -500,7 +470,6 @@ namespace System { this.SetValue(value, (int) index); } - [ComVisible(false)] public void SetValue(Object value, long index1, long index2) { if (index1 > Int32.MaxValue || index1 < Int32.MinValue) @@ -512,7 +481,6 @@ namespace System { this.SetValue(value, (int) index1, (int) index2); } - [ComVisible(false)] public void SetValue(Object value, long index1, long index2, long index3) { if (index1 > Int32.MaxValue || index1 < Int32.MinValue) @@ -526,7 +494,6 @@ namespace System { this.SetValue(value, (int) index1, (int) index2, (int) index3); } - [ComVisible(false)] public void SetValue(Object value, params long[] indices) { if (indices == null) @@ -559,12 +526,10 @@ namespace System { public extern int Length { [Pure] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImpl(MethodImplOptions.InternalCall)] get; } - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private static int GetMedian(int low, int hi) { // Note both may be negative, if we are dealing with arrays w/ negative lower bounds. Contract.Requires(low <= hi); @@ -580,10 +545,8 @@ namespace System { internal const int MaxArrayLength = 0X7FEFFFFF; internal const int MaxByteArrayLength = 0x7FFFFFC7; - [ComVisible(false)] public extern long LongLength { [Pure] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImpl(MethodImplOptions.InternalCall)] get; } @@ -593,7 +556,6 @@ namespace System { public extern int GetLength(int dimension); [Pure] - [ComVisible(false)] public long GetLongLength(int dimension) { //This method should throw an IndexOufOfRangeException for compat if dimension < 0 or >= Rank return GetLength(dimension); @@ -601,22 +563,18 @@ namespace System { public extern int Rank { [Pure] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImplAttribute(MethodImplOptions.InternalCall)] get; } [Pure] [MethodImplAttribute(MethodImplOptions.InternalCall)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] public extern int GetUpperBound(int dimension); [Pure] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern int GetLowerBound(int dimension); - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern int GetDataPtrOffsetInternal(); @@ -783,7 +741,6 @@ namespace System { // is larger than the given search value. // [Pure] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int BinarySearch(Array array, Object value) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -807,7 +764,6 @@ namespace System { // is larger than the given search value. // [Pure] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int BinarySearch(Array array, int index, int length, Object value) { return BinarySearch(array, index, length, value, null); } @@ -827,7 +783,6 @@ namespace System { // is larger than the given search value. // [Pure] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int BinarySearch(Array array, Object value, IComparer comparer) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -852,7 +807,6 @@ namespace System { // is larger than the given search value. // [Pure] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int BinarySearch(Array array, int index, int length, Object value, IComparer comparer) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -923,11 +877,9 @@ namespace System { } [MethodImplAttribute(MethodImplOptions.InternalCall)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private static extern bool TrySZBinarySearch(Array sourceArray, int sourceIndex, int count, Object value, out int retVal); [Pure] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int BinarySearch<T>(T[] array, T value) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -936,7 +888,6 @@ namespace System { } [Pure] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int BinarySearch<T>(T[] array, T value, System.Collections.Generic.IComparer<T> comparer) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -945,13 +896,11 @@ namespace System { } [Pure] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int BinarySearch<T>(T[] array, int index, int length, T value) { return BinarySearch<T>(array, index, length, value, null); } [Pure] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int BinarySearch<T>(T[] array, int index, int length, T value, System.Collections.Generic.IComparer<T> comparer) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -1004,7 +953,6 @@ namespace System { } [Pure] - [ComVisible(false)] public void CopyTo(Array array, long index) { if (index > Int32.MaxValue || index < Int32.MinValue) @@ -1015,7 +963,6 @@ namespace System { } [Pure] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static T[] Empty<T>() { Contract.Ensures(Contract.Result<T[]>() != null); @@ -1253,7 +1200,6 @@ namespace System { // The array is searched forwards, and the elements of the array are // compared to the given value using the Object.Equals method. // - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int IndexOf(Array array, Object value) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -1269,7 +1215,6 @@ namespace System { // elements of the array are compared to the given value using the // Object.Equals method. // - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int IndexOf(Array array, Object value, int startIndex) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -1285,7 +1230,6 @@ namespace System { // elements of the array are compared to the given value using the // Object.Equals method. // - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int IndexOf(Array array, Object value, int startIndex, int count) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -1380,7 +1324,6 @@ namespace System { } [MethodImplAttribute(MethodImplOptions.InternalCall)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private static extern bool TrySZIndexOf(Array sourceArray, int sourceIndex, int count, Object value, out int retVal); @@ -1388,7 +1331,6 @@ namespace System { // The array is searched backwards, and the elements of the array are // compared to the given value using the Object.Equals method. // - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int LastIndexOf(Array array, Object value) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -1403,7 +1345,6 @@ namespace System { // startIndex and ending at index 0. The elements of the array are // compared to the given value using the Object.Equals method. // - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int LastIndexOf(Array array, Object value, int startIndex) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -1419,7 +1360,6 @@ namespace System { // the array are compared to the given value using the Object.Equals // method. // - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public static int LastIndexOf(Array array, Object value, int startIndex, int count) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -1531,7 +1471,6 @@ namespace System { } [MethodImplAttribute(MethodImplOptions.InternalCall)] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] private static extern bool TrySZLastIndexOf(Array sourceArray, int sourceIndex, int count, Object value, out int retVal); @@ -1540,7 +1479,6 @@ namespace System { // located at index length - i - 1, where length is the // length of the array. // - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Reverse(Array array) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -1554,7 +1492,6 @@ namespace System { // index index + (index + count - i - 1). // Reliability note: This may fail because it may have to box objects. // - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Reverse(Array array, int index, int length) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -1598,10 +1535,8 @@ namespace System { } [MethodImplAttribute(MethodImplOptions.InternalCall)] - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] private static extern bool TrySZReverse(Array array, int index, int count); - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Reverse<T>(T[] array) { if (array == null) @@ -1610,7 +1545,6 @@ namespace System { Reverse(array, 0, array.Length); } - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Reverse<T>(T[] array, int index, int length) { if (array == null) @@ -1639,7 +1573,6 @@ namespace System { // other using the IComparable interface, which must be implemented // by all elements of the array. // - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort(Array array) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -1653,7 +1586,6 @@ namespace System { // keys to each other using the IComparable interface, which must be // implemented by all elements of the keys array. // - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort(Array keys, Array items) { if (keys==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys); @@ -1665,7 +1597,6 @@ namespace System { // elements to each other using the IComparable interface, which // must be implemented by all elements in the given section of the array. // - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort(Array array, int index, int length) { Sort(array, null, index, length, null); } @@ -1676,7 +1607,6 @@ namespace System { // keys to each other using the IComparable interface, which must be // implemented by all elements of the keys array. // - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort(Array keys, Array items, int index, int length) { Sort(keys, items, index, length, null); } @@ -1687,7 +1617,6 @@ namespace System { // IComparable interface, which in that case must be implemented by // all elements of the array. // - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort(Array array, IComparer comparer) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -1703,7 +1632,6 @@ namespace System { // the IComparable interface, which in that case must be implemented // by all elements of the keys array. // - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort(Array keys, Array items, IComparer comparer) { if (keys==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys); @@ -1717,7 +1645,6 @@ namespace System { // the IComparable interface, which in that case must be implemented // by all elements in the given section of the array. // - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort(Array array, int index, int length, IComparer comparer) { Sort(array, null, index, length, comparer); } @@ -1730,7 +1657,6 @@ namespace System { // the IComparable interface, which in that case must be implemented // by all elements of the given section of the keys array. // - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort(Array keys, Array items, int index, int length, IComparer comparer) { if (keys==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys); @@ -1772,10 +1698,8 @@ namespace System { } [MethodImplAttribute(MethodImplOptions.InternalCall)] - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] private static extern bool TrySZSort(Array keys, Array items, int left, int right); - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort<T>(T[] array) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -1783,7 +1707,6 @@ namespace System { Sort<T>(array, 0, array.Length, null); } - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items) { if (keys==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys); @@ -1791,17 +1714,14 @@ namespace System { Sort<TKey, TValue>(keys, items, 0, keys.Length, null); } - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort<T>(T[] array, int index, int length) { Sort<T>(array, index, length, null); } - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, int index, int length) { Sort<TKey, TValue>(keys, items, index, length, null); } - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort<T>(T[] array, System.Collections.Generic.IComparer<T> comparer) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -1809,7 +1729,6 @@ namespace System { Sort<T>(array, 0, array.Length, comparer); } - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, System.Collections.Generic.IComparer<TKey> comparer) { if (keys==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys); @@ -1817,7 +1736,6 @@ namespace System { Sort<TKey, TValue>(keys, items, 0, keys.Length, comparer); } - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort<T>(T[] array, int index, int length, System.Collections.Generic.IComparer<T> comparer) { if (array==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -1840,7 +1758,6 @@ namespace System { } } - [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)] public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, int index, int length, System.Collections.Generic.IComparer<TKey> comparer) { if (keys==null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys); diff --git a/src/mscorlib/src/System/ArraySegment.cs b/src/mscorlib/src/System/ArraySegment.cs index b767e7bd77..03556e492a 100644 --- a/src/mscorlib/src/System/ArraySegment.cs +++ b/src/mscorlib/src/System/ArraySegment.cs @@ -15,8 +15,6 @@ using System.Collections; using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Diagnostics; using System.Diagnostics.Contracts; namespace System @@ -46,14 +44,10 @@ namespace System public ArraySegment(T[] array, int offset, int count) { - if (array == null) - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - if (offset < 0) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.offset, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); - if (count < 0) - ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum); - if (array.Length - offset < count) - ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); + // Validate arguments, check is minimal instructions with reduced branching for inlinable fast-path + // Failure should be rare and location determination and message is delegated to failure functions + if (array == null || (offset | count) < 0 || (array.Length - offset < count)) + ThrowHelper.ThrowArraySegmentCtorValidationFailedExceptions(array, offset, count); Contract.EndContractBlock(); _array = array; diff --git a/src/mscorlib/src/System/ArrayTypeMismatchException.cs b/src/mscorlib/src/System/ArrayTypeMismatchException.cs index 4f24b9d3c7..3e941fdf8e 100644 --- a/src/mscorlib/src/System/ArrayTypeMismatchException.cs +++ b/src/mscorlib/src/System/ArrayTypeMismatchException.cs @@ -11,42 +11,41 @@ ** =============================================================================*/ -namespace System { - - using System; - using System.Runtime.Serialization; +using System.Runtime.Serialization; + +namespace System +{ // The ArrayMismatchException is thrown when an attempt to store // an object of the wrong type within an array occurs. // - [System.Runtime.InteropServices.ComVisible(true)] [Serializable] - public class ArrayTypeMismatchException : SystemException { - + 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. - public ArrayTypeMismatchException() - : base(Environment.GetResourceString("Arg_ArrayTypeMismatchException")) { - SetErrorCode(__HResults.COR_E_ARRAYTYPEMISMATCH); + public ArrayTypeMismatchException() + : base(SR.Arg_ArrayTypeMismatchException) + { + HResult = __HResults.COR_E_ARRAYTYPEMISMATCH; } - + // 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. // - public ArrayTypeMismatchException(String message) - : base(message) { - SetErrorCode(__HResults.COR_E_ARRAYTYPEMISMATCH); - } - - public ArrayTypeMismatchException(String message, Exception innerException) - : base(message, innerException) { - SetErrorCode(__HResults.COR_E_ARRAYTYPEMISMATCH); + public ArrayTypeMismatchException(String message) + : base(message) + { + HResult = __HResults.COR_E_ARRAYTYPEMISMATCH; } - protected ArrayTypeMismatchException(SerializationInfo info, StreamingContext context) : base(info, context) { + public ArrayTypeMismatchException(String message, Exception innerException) + : base(message, innerException) + { + HResult = __HResults.COR_E_ARRAYTYPEMISMATCH; } + protected ArrayTypeMismatchException(SerializationInfo info, StreamingContext context) : base(info, context) { } } - } diff --git a/src/mscorlib/src/System/AsyncCallback.cs b/src/mscorlib/src/System/AsyncCallback.cs index 69a03812e1..5c49535cff 100644 --- a/src/mscorlib/src/System/AsyncCallback.cs +++ b/src/mscorlib/src/System/AsyncCallback.cs @@ -9,9 +9,9 @@ ** Purpose: Type of callback for async operations ** ===========================================================*/ -namespace System { + +namespace System +{ [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] public delegate void AsyncCallback(IAsyncResult ar); - } diff --git a/src/mscorlib/src/System/Attribute.cs b/src/mscorlib/src/System/Attribute.cs index e77450e972..b44e13f959 100644 --- a/src/mscorlib/src/System/Attribute.cs +++ b/src/mscorlib/src/System/Attribute.cs @@ -13,14 +13,10 @@ namespace System { using System.Diagnostics; using System.Diagnostics.Contracts; using System.Security; - using System.Security.Permissions; [Serializable] [AttributeUsageAttribute(AttributeTargets.All, Inherited = true, AllowMultiple=false)] - [ClassInterface(ClassInterfaceType.None)] - [ComDefaultInterface(typeof(_Attribute))] - [System.Runtime.InteropServices.ComVisible(true)] - public abstract class Attribute : _Attribute + public abstract class Attribute { #region Private Statics diff --git a/src/mscorlib/src/System/AttributeTargets.cs b/src/mscorlib/src/System/AttributeTargets.cs index 33617e9623..fdfa4ab730 100644 --- a/src/mscorlib/src/System/AttributeTargets.cs +++ b/src/mscorlib/src/System/AttributeTargets.cs @@ -4,37 +4,33 @@ //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -namespace System { - - using System; - + +namespace System +{ // Enum used to indicate all the elements of the // VOS it is valid to attach this element to. -[Serializable] [Flags] -[System.Runtime.InteropServices.ComVisible(true)] + [Serializable] public enum AttributeTargets { - Assembly = 0x0001, - Module = 0x0002, - Class = 0x0004, - Struct = 0x0008, - Enum = 0x0010, - Constructor = 0x0020, - Method = 0x0040, - Property = 0x0080, - Field = 0x0100, - Event = 0x0200, - Interface = 0x0400, - Parameter = 0x0800, - Delegate = 0x1000, - ReturnValue = 0x2000, - //@todo GENERICS: document GenericParameter + Assembly = 0x0001, + Module = 0x0002, + Class = 0x0004, + Struct = 0x0008, + Enum = 0x0010, + Constructor = 0x0020, + Method = 0x0040, + Property = 0x0080, + Field = 0x0100, + Event = 0x0200, + Interface = 0x0400, + Parameter = 0x0800, + Delegate = 0x1000, + ReturnValue = 0x2000, GenericParameter = 0x4000, - - - All = Assembly | Module | Class | Struct | Enum | Constructor | - Method | Property | Field | Event | Interface | Parameter | - Delegate | ReturnValue | GenericParameter, + + All = Assembly | Module | Class | Struct | Enum | Constructor | + Method | Property | Field | Event | Interface | Parameter | + Delegate | ReturnValue | GenericParameter } } diff --git a/src/mscorlib/src/System/AttributeUsageAttribute.cs b/src/mscorlib/src/System/AttributeUsageAttribute.cs index 0c2e11caff..33f7fd805e 100644 --- a/src/mscorlib/src/System/AttributeUsageAttribute.cs +++ b/src/mscorlib/src/System/AttributeUsageAttribute.cs @@ -16,7 +16,6 @@ namespace System { /* By default, attributes are inherited and multiple attributes are not allowed */ [Serializable] [AttributeUsage(AttributeTargets.Class, Inherited = true)] -[System.Runtime.InteropServices.ComVisible(true)] public sealed class AttributeUsageAttribute : Attribute { internal AttributeTargets m_attributeTarget = AttributeTargets.All; // Defaults to all diff --git a/src/mscorlib/src/System/BCLDebug.cs b/src/mscorlib/src/System/BCLDebug.cs index 0ca6e616f2..7556b85789 100644 --- a/src/mscorlib/src/System/BCLDebug.cs +++ b/src/mscorlib/src/System/BCLDebug.cs @@ -20,7 +20,6 @@ namespace System { using Microsoft.Win32; using System.Runtime.CompilerServices; using System.Runtime.Versioning; - using System.Security.Permissions; using System.Security; using System.Diagnostics.Contracts; @@ -54,7 +53,6 @@ namespace System { #if _DEBUG internal static volatile bool m_domainUnloadAdded; #endif - internal static volatile PermissionSet m_MakeConsoleErrorLoggingWork; static readonly SwitchStructure[] switches = { new SwitchStructure("NLS", 0x00000001), @@ -263,40 +261,6 @@ namespace System { System.Diagnostics.Log.LogMessage((LoggingLevels)((int)level), logSwitch, StringBuilderCache.GetStringAndRelease(sb)); } - // Note this overload doesn't take a format string. You probably don't - // want this one. - [Pure] - [Conditional("_LOGGING")] - public static void Trace(String switchName, params Object[]messages) { - if (m_loggingNotEnabled) { - return; - } - - LogSwitch logSwitch; - if (!CheckEnabled(switchName, LogLevel.Trace, out logSwitch)) { - return; - } - - StringBuilder sb = StringBuilderCache.Acquire(); - - for (int i=0; i<messages.Length; i++) { - String s; - try { - if (messages[i]==null) { - s = "<null>"; - } else { - s = messages[i].ToString(); - } - } catch { - s = "<unable to convert>"; - } - sb.Append(s); - } - - sb.Append(Environment.NewLine); - System.Diagnostics.Log.LogMessage(LoggingLevels.TraceLevel0, logSwitch, StringBuilderCache.GetStringAndRelease(sb)); - } - [Pure] [Conditional("_LOGGING")] public static void Trace(String switchName, String format, params Object[] messages) { @@ -316,22 +280,6 @@ namespace System { System.Diagnostics.Log.LogMessage(LoggingLevels.TraceLevel0, logSwitch, StringBuilderCache.GetStringAndRelease(sb)); } - [Conditional("_LOGGING")] - public static void DumpStack(String switchName) { - LogSwitch logSwitch; - - if (!m_registryChecked) { - CheckRegistry(); - } - - if (!CheckEnabled(switchName, LogLevel.Trace, out logSwitch)) { - return; - } - - StackTrace trace = new StackTrace(); - System.Diagnostics.Log.LogMessage(LoggingLevels.TraceLevel0, logSwitch, trace.ToString()); - } - // For perf-related asserts. On a debug build, set the registry key // BCLPerfWarnings to non-zero. [Conditional("_DEBUG")] @@ -377,21 +325,6 @@ namespace System { #endif } -#if !BIT64 // 32 -#endif - internal static bool CorrectnessEnabled() - { -#if BIT64 - return false; -#else // 32 - if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize()) - return false; - if (!m_registryChecked) - CheckRegistry(); - return m_correctnessWarnings; -#endif // BIT64 - } - // Whether SafeHandles include a stack trace showing where they // were allocated. Only useful in checked & debug builds. internal static bool SafeHandleStackTracesEnabled { diff --git a/src/mscorlib/src/System/BadImageFormatException.cs b/src/mscorlib/src/System/BadImageFormatException.cs index 3f3f4a5b6e..51a6c40771 100644 --- a/src/mscorlib/src/System/BadImageFormatException.cs +++ b/src/mscorlib/src/System/BadImageFormatException.cs @@ -16,11 +16,9 @@ namespace System { using System; using System.Runtime.Serialization; using FileLoadException = System.IO.FileLoadException; - using System.Security.Permissions; using SecurityException = System.Security.SecurityException; using System.Globalization; - [System.Runtime.InteropServices.ComVisible(true)] [Serializable] public class BadImageFormatException : SystemException { diff --git a/src/mscorlib/src/System/BitConverter.cs b/src/mscorlib/src/System/BitConverter.cs index 3a6d1c03b0..07af5a8178 100644 --- a/src/mscorlib/src/System/BitConverter.cs +++ b/src/mscorlib/src/System/BitConverter.cs @@ -63,7 +63,7 @@ namespace System { Contract.Ensures(Contract.Result<byte[]>().Length == 2); byte[] bytes = new byte[2]; - fixed(byte* b = bytes) + fixed(byte* b = &bytes[0]) *((short*)b) = value; return bytes; } @@ -76,7 +76,7 @@ namespace System { Contract.Ensures(Contract.Result<byte[]>().Length == 4); byte[] bytes = new byte[4]; - fixed(byte* b = bytes) + fixed(byte* b = &bytes[0]) *((int*)b) = value; return bytes; } @@ -89,7 +89,7 @@ namespace System { Contract.Ensures(Contract.Result<byte[]>().Length == 8); byte[] bytes = new byte[8]; - fixed(byte* b = bytes) + fixed(byte* b = &bytes[0]) *((long*)b) = value; return bytes; } diff --git a/src/mscorlib/src/System/Boolean.cs b/src/mscorlib/src/System/Boolean.cs index 9aaec9a345..c085b0a020 100644 --- a/src/mscorlib/src/System/Boolean.cs +++ b/src/mscorlib/src/System/Boolean.cs @@ -19,7 +19,6 @@ namespace System { // The Boolean class provides the // object representation of the boolean primitive type. [Serializable] -[System.Runtime.InteropServices.ComVisible(true)] public struct Boolean : IComparable, IConvertible, IComparable<Boolean>, IEquatable<Boolean> { diff --git a/src/mscorlib/src/System/Buffer.cs b/src/mscorlib/src/System/Buffer.cs index eee2a81b51..662b240b34 100644 --- a/src/mscorlib/src/System/Buffer.cs +++ b/src/mscorlib/src/System/Buffer.cs @@ -22,7 +22,6 @@ namespace System { using nuint = System.UInt32; #endif // BIT64 -[System.Runtime.InteropServices.ComVisible(true)] public static class Buffer { // Copies from one primitive array to another primitive array without @@ -205,7 +204,6 @@ namespace System { *(src + len) = 0; } - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal unsafe static void Memcpy(byte[] dest, int destIndex, byte* src, int srcIndex, int len) { 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"); @@ -218,7 +216,6 @@ namespace System { } } - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal unsafe static void Memcpy(byte* pDest, int destIndex, byte[] src, int srcIndex, int len) { Debug.Assert( (srcIndex >= 0) && (destIndex >= 0) && (len >= 0), "Index and length must be non-negative!"); @@ -242,7 +239,6 @@ namespace System { // 1. This method is given access to other internal dlls and this close to release we do not want to change it. // 2. It is difficult to get this right for arm and again due to release dates we would like to visit it later. [FriendAccessAllowed] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] #if ARM [MethodImplAttribute(MethodImplOptions.InternalCall)] internal unsafe static extern void Memcpy(byte* dest, byte* src, int len); @@ -255,7 +251,6 @@ namespace System { #endif // ARM // This method has different signature for x64 and other platforms and is done for performance reasons. - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] internal unsafe static void Memmove(byte* dest, byte* src, nuint len) { // P/Invoke into the native version when the buffers are overlapping and the copy needs to be performed backwards @@ -581,7 +576,6 @@ namespace System { // Non-inlinable wrapper around the QCall that avoids poluting the fast path // with P/Invoke prolog/epilog. - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [MethodImplAttribute(MethodImplOptions.NoInlining)] private unsafe static void _Memmove(byte* dest, byte* src, nuint len) { @@ -590,7 +584,6 @@ namespace System { [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] extern private unsafe static void __Memmove(byte* dest, byte* src, nuint len); // The attributes on this method are chosen for best JIT performance. diff --git a/src/mscorlib/src/System/ByReference.cs b/src/mscorlib/src/System/ByReference.cs index 6f8bb2281e..833dab0d55 100644 --- a/src/mscorlib/src/System/ByReference.cs +++ b/src/mscorlib/src/System/ByReference.cs @@ -15,16 +15,20 @@ namespace System public ByReference(ref T value) { - // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead - unsafe { _value = (IntPtr)Unsafe.AsPointer(ref value); } + // 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 System.PlatformNotSupportedException(); } public ref T Value { get { - // TODO-SPAN: This has GC hole. It needs to be JIT intrinsic instead - unsafe { return ref Unsafe.As<IntPtr, T>(ref *(IntPtr*)_value); } + // 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 System.PlatformNotSupportedException(); } } } diff --git a/src/mscorlib/src/System/Byte.cs b/src/mscorlib/src/System/Byte.cs index 980412b69e..666fdda75b 100644 --- a/src/mscorlib/src/System/Byte.cs +++ b/src/mscorlib/src/System/Byte.cs @@ -22,7 +22,6 @@ namespace System { // The Byte class extends the Value class and // provides object representation of the byte primitive type. // -[System.Runtime.InteropServices.ComVisible(true)] [Serializable] [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)] public struct Byte : IComparable, IFormattable, IConvertible diff --git a/src/mscorlib/src/System/CLRConfig.cs b/src/mscorlib/src/System/CLRConfig.cs index 01ad7c31ab..16c610b82b 100644 --- a/src/mscorlib/src/System/CLRConfig.cs +++ b/src/mscorlib/src/System/CLRConfig.cs @@ -9,26 +9,6 @@ using System.Security; namespace System { -/// <summary> -/// For now, this class should be the central point to collect all managed declarations -/// of native functions designed to expose config switches. -/// In Dev11 M2.2 we will redesign this class to expose CLRConfig from within the CLR -/// and refactor managed Fx code to access all compat switches through here. -/// </summary> -[FriendAccessAllowed] -internal class CLRConfig { - - [FriendAccessAllowed] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SuppressUnmanagedCodeSecurity] - internal static extern bool CheckLegacyManagedDeflateStream(); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [SuppressUnmanagedCodeSecurity] - internal static extern bool CheckThrowUnobservedTaskExceptions(); - -} // internal class CLRConfig - } // namespace System // file CLRConfig diff --git a/src/mscorlib/src/System/CLSCompliantAttribute.cs b/src/mscorlib/src/System/CLSCompliantAttribute.cs index e902049558..e03600d132 100644 --- a/src/mscorlib/src/System/CLSCompliantAttribute.cs +++ b/src/mscorlib/src/System/CLSCompliantAttribute.cs @@ -11,23 +11,23 @@ ** =============================================================================*/ -namespace System { -[Serializable] - [AttributeUsage (AttributeTargets.All, Inherited=true, AllowMultiple=false)] -[System.Runtime.InteropServices.ComVisible(true)] - public sealed class CLSCompliantAttribute : Attribute +namespace System +{ + [Serializable] + [AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = false)] + public sealed class CLSCompliantAttribute : Attribute { - private bool m_compliant; + private bool _compliant; - public CLSCompliantAttribute (bool isCompliant) + public CLSCompliantAttribute(bool isCompliant) { - m_compliant = isCompliant; + _compliant = isCompliant; } - public bool IsCompliant + public bool IsCompliant { - get + get { - return m_compliant; + return _compliant; } } } diff --git a/src/mscorlib/src/System/CannotUnloadAppDomainException.cs b/src/mscorlib/src/System/CannotUnloadAppDomainException.cs deleted file mode 100644 index 6b07eae5e2..0000000000 --- a/src/mscorlib/src/System/CannotUnloadAppDomainException.cs +++ /dev/null @@ -1,49 +0,0 @@ -// 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. - -/*============================================================================= -** -** -** -** Purpose: Exception class for failed attempt to unload an AppDomain. -** -** -=============================================================================*/ - -namespace System { - - using System.Runtime.Serialization; - - [System.Runtime.InteropServices.ComVisible(true)] - [Serializable] - public class CannotUnloadAppDomainException : SystemException { - public CannotUnloadAppDomainException() - : base(Environment.GetResourceString("Arg_CannotUnloadAppDomainException")) { - SetErrorCode(__HResults.COR_E_CANNOTUNLOADAPPDOMAIN); - } - - public CannotUnloadAppDomainException(String message) - : base(message) { - SetErrorCode(__HResults.COR_E_CANNOTUNLOADAPPDOMAIN); - } - - public CannotUnloadAppDomainException(String message, Exception innerException) - : base(message, innerException) { - SetErrorCode(__HResults.COR_E_CANNOTUNLOADAPPDOMAIN); - } - - // - //This constructor is required for serialization. - // - protected CannotUnloadAppDomainException(SerializationInfo info, StreamingContext context) : base(info, context) { - } - } -} - - - - - - - diff --git a/src/mscorlib/src/System/CfgParser.cs b/src/mscorlib/src/System/CfgParser.cs deleted file mode 100644 index b21da7fe94..0000000000 --- a/src/mscorlib/src/System/CfgParser.cs +++ /dev/null @@ -1,564 +0,0 @@ -// 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. - -/*============================================================ - ** - ** - ** - ** Purpose: XMLParser and Tree builder internal to BCL - ** - ** - ===========================================================*/ - -namespace System -{ - using System.Runtime.InteropServices; - using System.Collections; - using System.Collections.Generic; - using System.Runtime.CompilerServices; - using System.Security.Permissions; - using System.Security; - using System.Globalization; - using System.IO; - using System.Runtime.Versioning; - using System.Diagnostics.Contracts; - - [Serializable] - internal enum ConfigEvents - { - StartDocument = 0, - StartDTD = StartDocument + 1, - EndDTD = StartDTD + 1, - StartDTDSubset = EndDTD + 1, - EndDTDSubset = StartDTDSubset + 1, - EndProlog = EndDTDSubset + 1, - StartEntity = EndProlog + 1, - EndEntity = StartEntity + 1, - EndDocument = EndEntity + 1, - DataAvailable = EndDocument + 1, - LastEvent = DataAvailable - } - - [Serializable] - internal enum ConfigNodeType - { - Element = 1, - Attribute = Element + 1, - Pi = Attribute + 1, - XmlDecl = Pi + 1, - DocType = XmlDecl + 1, - DTDAttribute = DocType + 1, - EntityDecl = DTDAttribute + 1, - ElementDecl = EntityDecl + 1, - AttlistDecl = ElementDecl + 1, - Notation = AttlistDecl + 1, - Group = Notation + 1, - IncludeSect = Group + 1, - PCData = IncludeSect + 1, - CData = PCData + 1, - IgnoreSect = CData + 1, - Comment = IgnoreSect + 1, - EntityRef = Comment + 1, - Whitespace = EntityRef + 1, - Name = Whitespace + 1, - NMToken = Name + 1, - String = NMToken + 1, - Peref = String + 1, - Model = Peref + 1, - ATTDef = Model + 1, - ATTType = ATTDef + 1, - ATTPresence = ATTType + 1, - DTDSubset = ATTPresence + 1, - LastNodeType = DTDSubset + 1 - } - - [Serializable] - internal enum ConfigNodeSubType - { - Version = (int)ConfigNodeType.LastNodeType, - Encoding = Version + 1, - Standalone = Encoding + 1, - NS = Standalone + 1, - XMLSpace = NS + 1, - XMLLang = XMLSpace + 1, - System = XMLLang + 1, - Public = System + 1, - NData = Public + 1, - AtCData = NData + 1, - AtId = AtCData + 1, - AtIdref = AtId + 1, - AtIdrefs = AtIdref + 1, - AtEntity = AtIdrefs + 1, - AtEntities = AtEntity + 1, - AtNmToken = AtEntities + 1, - AtNmTokens = AtNmToken + 1, - AtNotation = AtNmTokens + 1, - AtRequired = AtNotation + 1, - AtImplied = AtRequired + 1, - AtFixed = AtImplied + 1, - PentityDecl = AtFixed + 1, - Empty = PentityDecl + 1, - Any = Empty + 1, - Mixed = Any + 1, - Sequence = Mixed + 1, - Choice = Sequence + 1, - Star = Choice + 1, - Plus = Star + 1, - Questionmark = Plus + 1, - LastSubNodeType = Questionmark + 1 - } - - internal abstract class BaseConfigHandler - { - // These delegates must be at the very start of the object - // This is necessary because unmanaged code takes a dependency on this layout - // Any changes made to this must be reflected in ConfigHelper.h in ConfigFactory class - protected Delegate[] eventCallbacks; - public BaseConfigHandler() - { - InitializeCallbacks(); - } - private void InitializeCallbacks() - { - if (eventCallbacks == null) - { - eventCallbacks = new Delegate[6]; - eventCallbacks[0] = new NotifyEventCallback(this.NotifyEvent); - eventCallbacks[1] = new BeginChildrenCallback(this.BeginChildren); - eventCallbacks[2] = new EndChildrenCallback(this.EndChildren); - eventCallbacks[3] = new ErrorCallback(this.Error); - eventCallbacks[4] = new CreateNodeCallback(this.CreateNode); - eventCallbacks[5] = new CreateAttributeCallback(this.CreateAttribute); - } - } - - private delegate void NotifyEventCallback(ConfigEvents nEvent); - public abstract void NotifyEvent(ConfigEvents nEvent); - - private delegate void BeginChildrenCallback(int size, - ConfigNodeSubType subType, - ConfigNodeType nType, - int terminal, - [MarshalAs(UnmanagedType.LPWStr)] String text, - int textLength, - int prefixLength); - public abstract void BeginChildren(int size, - ConfigNodeSubType subType, - ConfigNodeType nType, - int terminal, - [MarshalAs(UnmanagedType.LPWStr)] String text, - int textLength, - int prefixLength); - - private delegate void EndChildrenCallback(int fEmpty, - int size, - ConfigNodeSubType subType, - ConfigNodeType nType, - int terminal, - [MarshalAs(UnmanagedType.LPWStr)] String text, - int textLength, - int prefixLength); - public abstract void EndChildren(int fEmpty, - int size, - ConfigNodeSubType subType, - ConfigNodeType nType, - int terminal, - [MarshalAs(UnmanagedType.LPWStr)] String text, - int textLength, - int prefixLength); - - private delegate void ErrorCallback(int size, - ConfigNodeSubType subType, - ConfigNodeType nType, - int terminal, - [MarshalAs(UnmanagedType.LPWStr)]String text, - int textLength, - int prefixLength); - public abstract void Error(int size, - ConfigNodeSubType subType, - ConfigNodeType nType, - int terminal, - [MarshalAs(UnmanagedType.LPWStr)]String text, - int textLength, - int prefixLength); - - private delegate void CreateNodeCallback(int size, - ConfigNodeSubType subType, - ConfigNodeType nType, - int terminal, - [MarshalAs(UnmanagedType.LPWStr)]String text, - int textLength, - int prefixLength); - public abstract void CreateNode(int size, - ConfigNodeSubType subType, - ConfigNodeType nType, - int terminal, - [MarshalAs(UnmanagedType.LPWStr)]String text, - int textLength, - int prefixLength); - - private delegate void CreateAttributeCallback(int size, - ConfigNodeSubType subType, - ConfigNodeType nType, - int terminal, - [MarshalAs(UnmanagedType.LPWStr)]String text, - int textLength, - int prefixLength); - public abstract void CreateAttribute(int size, - ConfigNodeSubType subType, - ConfigNodeType nType, - int terminal, - [MarshalAs(UnmanagedType.LPWStr)]String text, - int textLength, - int prefixLength); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal extern void RunParser(String fileName); - } - - // Class used to build a DOM like tree of parsed XML - internal class ConfigTreeParser : BaseConfigHandler - { - ConfigNode rootNode = null; - ConfigNode currentNode = null; - String fileName = null; - int attributeEntry; - String key = null; - String [] treeRootPath = null; // element to start tree - bool parsing = false; - int depth = 0; - int pathDepth = 0; - int searchDepth = 0; - bool bNoSearchPath = false; - - // Track state for error message formatting - String lastProcessed = null; - bool lastProcessedEndElement; - - - // NOTE: This parser takes a path eg. /configuration/system.runtime.remoting - // and will return a node which matches this. - internal ConfigNode Parse(String fileName, String configPath) - { - return Parse(fileName, configPath, false); - } - - internal ConfigNode Parse(String fileName, String configPath, bool skipSecurityStuff) - { - if (fileName == null) - throw new ArgumentNullException(nameof(fileName)); - Contract.EndContractBlock(); - this.fileName = fileName; - if (configPath[0] == '/'){ - treeRootPath = configPath.Substring(1).Split('/'); - pathDepth = treeRootPath.Length - 1; - bNoSearchPath = false; - } - else{ - treeRootPath = new String[1]; - treeRootPath[0] = configPath; - bNoSearchPath = true; - } - - if (!skipSecurityStuff) { - (new FileIOPermission(FileIOPermissionAccess.Read, Path.GetFullPath(fileName))).Demand(); - } -#pragma warning disable 618 - (new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Assert(); -#pragma warning restore 618 - - try - { - RunParser(fileName); - } - catch(FileNotFoundException) { - throw; // Pass these through unadulterated. - } - catch(DirectoryNotFoundException) { - throw; // Pass these through unadulterated. - } - catch(UnauthorizedAccessException) { - throw; - } - catch(FileLoadException) { - throw; - } - catch(Exception inner) { - String message = GetInvalidSyntaxMessage(); - // Neither Exception nor ApplicationException are the "right" exceptions here. - // Desktop throws ApplicationException for backwards compatibility. - // On Silverlight we don't have ApplicationException, so fall back to Exception. - throw new Exception(message, inner); - } - return rootNode; - } - - public override void NotifyEvent(ConfigEvents nEvent) - { - BCLDebug.Trace("REMOTE", "NotifyEvent "+((Enum)nEvent).ToString()+"\n"); - } - - public override void BeginChildren(int size, - ConfigNodeSubType subType, - ConfigNodeType nType, - int terminal, - [MarshalAs(UnmanagedType.LPWStr)] String text, - int textLength, - int prefixLength) - { - //Trace("BeginChildren",size,subType,nType,terminal,text,textLength,prefixLength,0); - if (!parsing && - (!bNoSearchPath - && depth == (searchDepth + 1) - && String.Compare(text, treeRootPath[searchDepth], StringComparison.Ordinal) == 0)) - { - searchDepth++; - } - } - - public override void EndChildren(int fEmpty, - int size, - ConfigNodeSubType subType, - ConfigNodeType nType, - int terminal, - [MarshalAs(UnmanagedType.LPWStr)] String text, - int textLength, - int prefixLength) - { - lastProcessed = text; - lastProcessedEndElement = true; - if (parsing) - { - //Trace("EndChildren",size,subType,nType,terminal,text,textLength,prefixLength,fEmpty); - - if (currentNode == rootNode) - { - // End of section of tree which is parsed - parsing = false; - } - - currentNode = currentNode.Parent; - } - else if (nType == ConfigNodeType.Element){ - if(depth == searchDepth && String.Compare(text, treeRootPath[searchDepth - 1], StringComparison.Ordinal) == 0) - { - searchDepth--; - depth--; - } - else - depth--; - } - } - - public override void Error(int size, - ConfigNodeSubType subType, - ConfigNodeType nType, - int terminal, - [MarshalAs(UnmanagedType.LPWStr)]String text, - int textLength, - int prefixLength) - { - //Trace("Error",size,subType,nType,terminal,text,textLength,prefixLength,0); - } - - public override void CreateNode(int size, - ConfigNodeSubType subType, - ConfigNodeType nType, - int terminal, - [MarshalAs(UnmanagedType.LPWStr)]String text, - int textLength, - int prefixLength) - { - //Trace("CreateNode",size,subType,nType,terminal,text,textLength,prefixLength,0); - - if (nType == ConfigNodeType.Element) - { - // New Node - lastProcessed = text; - lastProcessedEndElement = false; - - if (parsing - || (bNoSearchPath && - String.Compare(text, treeRootPath[0], StringComparison.OrdinalIgnoreCase) == 0) - || (depth == searchDepth && searchDepth == pathDepth && - String.Compare(text, treeRootPath[pathDepth], StringComparison.OrdinalIgnoreCase) == 0 )) - { - parsing = true; - - ConfigNode parentNode = currentNode; - currentNode = new ConfigNode(text, parentNode); - if (rootNode == null) - rootNode = currentNode; - else - parentNode.AddChild(currentNode); - } - else - depth++; - } - else if (nType == ConfigNodeType.PCData) - { - // Data node - if (currentNode != null) - { - currentNode.Value = text; - } - } - } - - public override void CreateAttribute(int size, - ConfigNodeSubType subType, - ConfigNodeType nType, - int terminal, - [MarshalAs(UnmanagedType.LPWStr)]String text, - int textLength, - int prefixLength) - { - //Trace("CreateAttribute",size,subType,nType,terminal,text,textLength,prefixLength,0); - if (parsing) - { - // if the value of the attribute is null, the parser doesn't come back, so need to store the attribute when the - // attribute name is encountered - if (nType == ConfigNodeType.Attribute) - { - attributeEntry = currentNode.AddAttribute(text, ""); - key = text; - } - else if (nType == ConfigNodeType.PCData) - { - currentNode.ReplaceAttribute(attributeEntry, key, text); - } - else - { - String message = GetInvalidSyntaxMessage(); - // Neither Exception nor ApplicationException are the "right" exceptions here. - // Desktop throws ApplicationException for backwards compatibility. - // On Silverlight we don't have ApplicationException, so fall back to Exception. - throw new Exception(message); - } - } - } - -#if _DEBUG - [System.Diagnostics.Conditional("_LOGGING")] - private void Trace(String name, - int size, - ConfigNodeSubType subType, - ConfigNodeType nType, - int terminal, - [MarshalAs(UnmanagedType.LPWStr)]String text, - int textLength, - int prefixLength, int fEmpty) - { - - BCLDebug.Trace("REMOTE","Node "+name); - BCLDebug.Trace("REMOTE","text "+text); - BCLDebug.Trace("REMOTE","textLength "+textLength); - BCLDebug.Trace("REMOTE","size "+size); - BCLDebug.Trace("REMOTE","subType "+((Enum)subType).ToString()); - BCLDebug.Trace("REMOTE","nType "+((Enum)nType).ToString()); - BCLDebug.Trace("REMOTE","terminal "+terminal); - BCLDebug.Trace("REMOTE","prefixLength "+prefixLength); - BCLDebug.Trace("REMOTE","fEmpty "+fEmpty+"\n"); - } -#endif - - private String GetInvalidSyntaxMessage() - { - String lastProcessedTag = null; - - if (lastProcessed != null) - lastProcessedTag = (lastProcessedEndElement ? "</" : "<") + lastProcessed + ">"; - - return Environment.GetResourceString("XML_Syntax_InvalidSyntaxInFile", fileName, lastProcessedTag); - } - } - - // Node in Tree produced by ConfigTreeParser - internal class ConfigNode - { - String m_name = null; - String m_value = null; - ConfigNode m_parent = null; - List<ConfigNode> m_children = new List<ConfigNode>(5); - List<DictionaryEntry> m_attributes = new List<DictionaryEntry>(5); - - internal ConfigNode(String name, ConfigNode parent) - { - m_name = name; - m_parent = parent; - } - - internal String Name - { - get {return m_name;} - } - - internal String Value - { - get {return m_value;} - set {m_value = value;} - } - - internal ConfigNode Parent - { - get {return m_parent;} - } - - internal List<ConfigNode> Children - { - get {return m_children;} - } - - internal List<DictionaryEntry> Attributes - { - get {return m_attributes;} - } - - internal void AddChild(ConfigNode child) - { - child.m_parent = this; - m_children.Add(child); - } - - internal int AddAttribute(String key, String value) - { - m_attributes.Add(new DictionaryEntry(key, value)); - return m_attributes.Count-1; - } - - internal void ReplaceAttribute(int index, String key, String value) - { - m_attributes[index] = new DictionaryEntry(key, value); - } - -#if _DEBUG - [System.Diagnostics.Conditional("_LOGGING")] - internal void Trace() - { - BCLDebug.Trace("REMOTE","************ConfigNode************"); - BCLDebug.Trace("REMOTE","Name = "+m_name); - if (m_value != null) - BCLDebug.Trace("REMOTE","Value = "+m_value); - if (m_parent != null) - BCLDebug.Trace("REMOTE","Parent = "+m_parent.Name); - for (int i=0; i<m_attributes.Count; i++) - { - DictionaryEntry de = (DictionaryEntry)m_attributes[i]; - BCLDebug.Trace("REMOTE","Key = "+de.Key+" Value = "+de.Value); - } - - for (int i=0; i<m_children.Count; i++) - { - ((ConfigNode)m_children[i]).Trace(); - } - } -#endif - } -} - - - - - - diff --git a/src/mscorlib/src/System/Char.cs b/src/mscorlib/src/System/Char.cs index b9c9305932..7fe1c08715 100644 --- a/src/mscorlib/src/System/Char.cs +++ b/src/mscorlib/src/System/Char.cs @@ -21,7 +21,6 @@ namespace System { using System.Diagnostics; using System.Diagnostics.Contracts; -[System.Runtime.InteropServices.ComVisible(true)] [Serializable] [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)] public struct Char : IComparable, IConvertible , IComparable<Char>, IEquatable<Char> diff --git a/src/mscorlib/src/System/CharEnumerator.cs b/src/mscorlib/src/System/CharEnumerator.cs index d25294c7e2..689ed7e488 100644 --- a/src/mscorlib/src/System/CharEnumerator.cs +++ b/src/mscorlib/src/System/CharEnumerator.cs @@ -11,65 +11,71 @@ ** ** ============================================================*/ -namespace System { - using System.Collections; - using System.Collections.Generic; - using System.Diagnostics.Contracts; +using System.Collections; +using System.Collections.Generic; -[System.Runtime.InteropServices.ComVisible(true)] - [Serializable] - public sealed class CharEnumerator : IEnumerator, ICloneable, IEnumerator<char>, IDisposable { - private String str; - private int index; - private char currentElement; +namespace System +{ + public sealed class CharEnumerator : IEnumerator, IEnumerator<char>, IDisposable, ICloneable + { + private String _str; + private int _index; + private char _currentElement; - internal CharEnumerator(String str) { - Contract.Requires(str != null); - this.str = str; - this.index = -1; + internal CharEnumerator(String str) + { + _str = str; + _index = -1; } - public Object Clone() { + public object Clone() + { return MemberwiseClone(); } - - public bool MoveNext() { - if (index < (str.Length-1)) { - index++; - currentElement = str[index]; + + public bool MoveNext() + { + if (_index < (_str.Length - 1)) + { + _index++; + _currentElement = _str[_index]; return true; } else - index = str.Length; + _index = _str.Length; return false; - } - public void Dispose() { - if (str != null) - index = str.Length; - str = null; + public void Dispose() + { + if (_str != null) + _index = _str.Length; + _str = null; } - + /// <internalonly/> - Object IEnumerator.Current { + Object IEnumerator.Current + { get { return Current; } } - - public char Current { - get { - if (index == -1) - throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted)); - if (index >= str.Length) - throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded)); - return currentElement; + + public char Current + { + get + { + if (_index == -1) + throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted); + if (_index >= _str.Length) + throw new InvalidOperationException(SR.InvalidOperation_EnumEnded); + return _currentElement; } } - public void Reset() { - currentElement = (char)0; - index = -1; + public void Reset() + { + _currentElement = (char)0; + _index = -1; } } } diff --git a/src/mscorlib/src/System/Collections/ArrayList.cs b/src/mscorlib/src/System/Collections/ArrayList.cs index e7f121370b..53746e224e 100644 --- a/src/mscorlib/src/System/Collections/ArrayList.cs +++ b/src/mscorlib/src/System/Collections/ArrayList.cs @@ -18,7 +18,6 @@ namespace System.Collections { using System; using System.Runtime; using System.Security; - using System.Security.Permissions; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.Serialization; @@ -35,8 +34,7 @@ namespace System.Collections { [DebuggerTypeProxy(typeof(System.Collections.ArrayList.ArrayListDebugView))] [DebuggerDisplay("Count = {Count}")] [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] - public class ArrayList : IList, ICloneable + internal class ArrayList : IList, ICloneable { private Object[] _items; [ContractPublicPropertyName("Count")] @@ -47,12 +45,6 @@ namespace System.Collections { private const int _defaultCapacity = 4; private static readonly Object[] emptyArray = EmptyArray<Object>.Value; - - // Note: this constructor is a bogus constructor that does nothing - // and is for use only with SyncArrayList. - internal ArrayList( bool trash ) - { - } // Constructs a ArrayList. The list is initially empty and has a capacity // of zero. Upon adding the first element to the list the capacity is @@ -175,22 +167,6 @@ namespace System.Collections { _version++; } } - - // Creates a ArrayList wrapper for a particular IList. This does not - // copy the contents of the IList, but only wraps the ILIst. So any - // changes to the underlying list will affect the ArrayList. This would - // be useful if you want to Reverse a subrange of an IList, or want to - // use a generic BinarySearch or Sort method without implementing one yourself. - // However, since these methods are generic, the performance may not be - // nearly as good for some operations as they would be on the IList itself. - // - public static ArrayList Adapter(IList list) { - if (list==null) - throw new ArgumentNullException(nameof(list)); - Contract.Ensures(Contract.Result<ArrayList>() != null); - Contract.EndContractBlock(); - return new IListWrapper(list); - } // Adds the given object to the end of this list. The size of the list is // increased by one. If required, the capacity of the list is doubled @@ -211,52 +187,6 @@ namespace System.Collections { public virtual void AddRange(ICollection c) { InsertRange(_size, c); } - - // Searches a section of the list for a given element using a binary search - // algorithm. Elements of the list are compared to the search value using - // the given IComparer interface. If comparer is null, elements of - // the list are compared to the search value using the IComparable - // interface, which in that case must be implemented by all elements of the - // list and the given search value. This method assumes that the given - // section of the list 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 list. If the - // list 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. 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) - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (_size - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.Ensures(Contract.Result<int>() < Count); - Contract.Ensures(Contract.Result<int>() < index + count); - Contract.EndContractBlock(); - - return Array.BinarySearch((Array)_items, index, count, value, comparer); - } - - public virtual int BinarySearch(Object value) - { - Contract.Ensures(Contract.Result<int>() < Count); - return BinarySearch(0, Count, value, null); - } - - public virtual int BinarySearch(Object value, IComparer comparer) - { - Contract.Ensures(Contract.Result<int>() < Count); - return BinarySearch(0, Count, value, comparer); - } // Clears the contents of ArrayList. @@ -301,13 +231,6 @@ namespace System.Collections { return false; } } - - // 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. @@ -319,20 +242,6 @@ namespace System.Collections { // Delegate rest of error checking to Array.Copy. Array.Copy(_items, 0, array, arrayIndex, _size); } - - // 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) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - if ((array != null) && (array.Rank != 1)) - throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported")); - Contract.EndContractBlock(); - // Delegate rest of error checking to Array.Copy. - Array.Copy(_items, index, array, arrayIndex, count); - } // Ensures that the capacity of this list is at least the given minimum // value. If the currect capacity of the list is less than min, the @@ -349,28 +258,6 @@ namespace System.Collections { } } - // Returns a list wrapper that is fixed at the current size. Operations - // that add or remove items will fail, however, replacing items is allowed. - // - public static IList FixedSize(IList list) { - if (list==null) - throw new ArgumentNullException(nameof(list)); - Contract.Ensures(Contract.Result<IList>() != null); - Contract.EndContractBlock(); - return new FixedSizeList(list); - } - - // Returns a list wrapper that is fixed at the current size. Operations - // that add or remove items will fail, however, replacing items is allowed. - // - public static ArrayList FixedSize(ArrayList list) { - if (list==null) - throw new ArgumentNullException(nameof(list)); - Contract.Ensures(Contract.Result<ArrayList>() != null); - Contract.EndContractBlock(); - return new FixedSizeArrayList(list); - } - // 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 @@ -381,24 +268,6 @@ namespace System.Collections { return new ArrayListEnumeratorSimple(this); } - // 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 - // GetObject methods of the enumerator will throw an exception. - // - public virtual IEnumerator GetEnumerator(int index, int count) { - if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (_size - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.Ensures(Contract.Result<IEnumerator>() != null); - Contract.EndContractBlock(); - - return new ArrayListEnumerator(this, index, count); - } - // Returns the index of the first occurrence of a given value in a range of // this list. The list is searched forwards from beginning to end. // The elements of the list are compared to the given value using the @@ -412,41 +281,6 @@ namespace System.Collections { return Array.IndexOf((Array)_items, value, 0, _size); } - // Returns the index of the first occurrence of a given value in a range of - // this list. The list is searched forwards, starting at index - // 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) - throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); - Contract.Ensures(Contract.Result<int>() < Count); - Contract.EndContractBlock(); - return Array.IndexOf((Array)_items, value, startIndex, _size - startIndex); - } - - // Returns the index of the first occurrence of a given value in a range of - // this list. The list is searched forwards, starting at index - // startIndex 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 virtual int IndexOf(Object value, int startIndex, int count) { - if (startIndex > _size) - throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); - if (count <0 || startIndex > _size - count) throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); - Contract.Ensures(Contract.Result<int>() < Count); - Contract.EndContractBlock(); - return Array.IndexOf((Array)_items, value, startIndex, count); - } - // 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. @@ -494,62 +328,6 @@ namespace System.Collections { } } - // 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 - // 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) - { - Contract.Ensures(Contract.Result<int>() < _size); - 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 - // 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) - throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); - Contract.Ensures(Contract.Result<int>() < Count); - Contract.EndContractBlock(); - return LastIndexOf(value, startIndex, startIndex + 1); - } - - // 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 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 virtual int LastIndexOf(Object value, int startIndex, int count) { - if (Count != 0 && (startIndex < 0 || count < 0)) - throw new ArgumentOutOfRangeException((startIndex<0 ? nameof(startIndex) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - Contract.Ensures(Contract.Result<int>() < Count); - Contract.EndContractBlock(); - - if (_size == 0) // Special case for an empty list - return -1; - - if (startIndex >= _size || count > startIndex + 1) - throw new ArgumentOutOfRangeException((startIndex>=_size ? nameof(startIndex) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_BiggerThanCollection")); - - return Array.LastIndexOf((Array)_items, value, startIndex, count); - } - // Returns a read-only IList wrapper for the given IList. // [FriendAccessAllowed] @@ -560,16 +338,6 @@ namespace System.Collections { Contract.EndContractBlock(); return new ReadOnlyList(list); } - - // Returns a read-only ArrayList wrapper for the given ArrayList. - // - public static ArrayList ReadOnly(ArrayList list) { - if (list==null) - throw new ArgumentNullException(nameof(list)); - Contract.Ensures(Contract.Result<ArrayList>() != null); - Contract.EndContractBlock(); - return new ReadOnlyArrayList(list); - } // Removes the element at the given index. The size of the list is // decreased by one. @@ -600,159 +368,6 @@ namespace System.Collections { _version++; } - // Removes a range of elements from this list. - // - public virtual void RemoveRange(int index, int count) { - if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (_size - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.Ensures(Count >= 0); - //Contract.Ensures(Count == Contract.OldValue(Count) - count); - Contract.EndContractBlock(); - - if (count > 0) { - int i = _size; - _size -= count; - if (index < _size) { - Array.Copy(_items, index + count, _items, index, _size - index); - } - while (i > _size) _items[--i] = null; - _version++; - } - } - - // Returns an IList that contains count copies of value. - // - public static ArrayList Repeat(Object value, int count) { - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count),Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - Contract.Ensures(Contract.Result<ArrayList>() != null); - Contract.EndContractBlock(); - - ArrayList list = new ArrayList((count>_defaultCapacity)?count:_defaultCapacity); - for(int i=0; i<count; i++) - list.Add(value); - return list; - } - - // Reverses the elements in this list. - public virtual void Reverse() { - Reverse(0, Count); - } - - // Reverses the elements in a range of this list. Following a call to this - // 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) - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (_size - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - Array.Reverse(_items, index, count); - _version++; - } - - // Sets the elements starting at the given index to the elements of the - // given collection. - // - public virtual void SetRange(int index, ICollection c) { - if (c==null) throw new ArgumentNullException(nameof(c), Environment.GetResourceString("ArgumentNull_Collection")); - Contract.EndContractBlock(); - int count = c.Count; - if (index < 0 || index > _size - count) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); - - if (count > 0) { - c.CopyTo(_items, index); - _version++; - } - } - - public virtual ArrayList GetRange(int index, int count) { - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (_size - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.Ensures(Contract.Result<ArrayList>() != null); - Contract.EndContractBlock(); - return new Range(this,index, count); - } - - // Sorts the elements in this list. Uses the default comparer and - // Array.Sort. - public virtual void Sort() - { - Sort(0, Count, Comparer.Default); - } - - // Sorts the elements in this list. Uses Array.Sort with the - // provided comparer. - public virtual void Sort(IComparer comparer) - { - Sort(0, Count, comparer); - } - - // Sorts the elements in a section of this list. The sort compares the - // elements to each other using the given IComparer interface. If - // 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) - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (_size - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - Array.Sort(_items, index, count, comparer); - _version++; - } - - // Returns a thread-safe wrapper around an IList. - // - public static IList Synchronized(IList list) { - if (list==null) - throw new ArgumentNullException(nameof(list)); - Contract.Ensures(Contract.Result<IList>() != null); - Contract.EndContractBlock(); - return new SyncIList(list); - } - - // Returns a thread-safe wrapper around a ArrayList. - // - public static ArrayList Synchronized(ArrayList list) { - if (list==null) - throw new ArgumentNullException(nameof(list)); - Contract.Ensures(Contract.Result<ArrayList>() != null); - Contract.EndContractBlock(); - return new SyncArrayList(list); - } - - // ToArray returns a new Object array containing the contents of the ArrayList. - // This requires copying the ArrayList, which is an O(n) operation. - public virtual Object[] ToArray() { - Contract.Ensures(Contract.Result<Object[]>() != null); - - Object[] array = new Object[_size]; - Array.Copy(_items, 0, array, 0, _size); - return array; - } - // 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. @@ -768,1070 +383,6 @@ namespace System.Collections { return array; } - // Sets the capacity of this list to the size of the list. This method can - // be used to minimize a list's memory overhead once it is known that no - // 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; - } - - - // This class wraps an IList, exposing it as a ArrayList - // Note this requires reimplementing half of ArrayList... - [Serializable] - private class IListWrapper : ArrayList - { - private IList _list; - - internal IListWrapper(IList list) { - _list = list; - _version = 0; // list doesn't not contain a version number - } - - public override int Capacity { - get { return _list.Count; } - set { - if (value < Count) throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); - Contract.EndContractBlock(); - } - } - - public override int Count { - get { return _list.Count; } - } - - public override bool IsReadOnly { - get { return _list.IsReadOnly; } - } - - public override bool IsFixedSize { - get { return _list.IsFixedSize; } - } - - - public override bool IsSynchronized { - get { return _list.IsSynchronized; } - } - - public override Object this[int index] { - get { - return _list[index]; - } - set { - _list[index] = value; - _version++; - } - } - - public override Object SyncRoot { - get { return _list.SyncRoot; } - } - - public override int Add(Object obj) { - int i = _list.Add(obj); - _version++; - return i; - } - - public override void AddRange(ICollection c) { - InsertRange(Count, c); - } - - // Other overloads with automatically work - public override int BinarySearch(int index, int count, Object value, IComparer comparer) - { - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (this.Count - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - if (comparer == null) - comparer = Comparer.Default; - - int lo = index; - int hi = index + count - 1; - int mid; - while (lo <= hi) { - mid = (lo+hi)/2; - int r = comparer.Compare(value, _list[mid]); - if (r == 0) - return mid; - if (r < 0) - hi = mid-1; - else - lo = mid+1; - } - // return bitwise complement of the first element greater than value. - // Since hi is less than lo now, ~lo is the correct item. - return ~lo; - } - - public override void Clear() { - // If _list is an array, it will support Clear method. - // We shouldn't allow clear operation on a FixedSized ArrayList - if(_list.IsFixedSize) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); - } - - _list.Clear(); - _version++; - } - - public override Object Clone() { - // This does not do a shallow copy of _list into a ArrayList! - // This clones the IListWrapper, creating another wrapper class! - return new IListWrapper(_list); - } - - public override bool Contains(Object obj) { - return _list.Contains(obj); - } - - public override void CopyTo(Array array, int index) { - _list.CopyTo(array, index); - } - - public override void CopyTo(int index, Array array, int arrayIndex, int count) { - if (array==null) - throw new ArgumentNullException(nameof(array)); - if (index < 0 || arrayIndex < 0) - throw new ArgumentOutOfRangeException((index < 0) ? nameof(index) : nameof(arrayIndex), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if( count < 0) - throw new ArgumentOutOfRangeException( nameof(count) , Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (array.Length - arrayIndex < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - if (array.Rank != 1) - throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported")); - Contract.EndContractBlock(); - - if (_list.Count - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - - for(int i=index; i<index+count; i++) - array.SetValue(_list[i], arrayIndex++); - } - - public override IEnumerator GetEnumerator() { - return _list.GetEnumerator(); - } - - public override IEnumerator GetEnumerator(int index, int count) { - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - Contract.EndContractBlock(); - if (_list.Count - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - - return new IListWrapperEnumWrapper(this, index, count); - } - - public override int IndexOf(Object value) { - return _list.IndexOf(value); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int IndexOf(Object value, int startIndex) { - return IndexOf(value, startIndex, _list.Count - startIndex); - } - - public override int IndexOf(Object value, int startIndex, int count) { - if (startIndex < 0 || startIndex > this.Count) throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); - if (count < 0 || startIndex > this.Count - count) throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); - Contract.EndContractBlock(); - - int endIndex = startIndex + count; - if (value == null) { - for(int i=startIndex; i<endIndex; i++) - if (_list[i] == null) - return i; - return -1; - } else { - for(int i=startIndex; i<endIndex; i++) - if (_list[i] != null && _list[i].Equals(value)) - return i; - return -1; - } - } - - public override void Insert(int index, Object obj) { - _list.Insert(index, obj); - _version++; - } - - public override void InsertRange(int index, ICollection c) { - if (c==null) - throw new ArgumentNullException(nameof(c), Environment.GetResourceString("ArgumentNull_Collection")); - if (index < 0 || index > this.Count) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); - Contract.EndContractBlock(); - - if( c.Count > 0) { - ArrayList al = _list as ArrayList; - if( al != null) { - // 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); - } - else { - IEnumerator en = c.GetEnumerator(); - while(en.MoveNext()) { - _list.Insert(index++, en.Current); - } - } - _version++; - } - } - - public override int LastIndexOf(Object value) { - return LastIndexOf(value,_list.Count - 1, _list.Count); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int LastIndexOf(Object value, int startIndex) { - return LastIndexOf(value, startIndex, startIndex + 1); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int LastIndexOf(Object value, int startIndex, int count) { - if (_list.Count == 0) - return -1; - - if (startIndex < 0 || startIndex >= _list.Count) throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); - if (count < 0 || count > startIndex + 1) throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); - - int endIndex = startIndex - count + 1; - if (value == null) { - for(int i=startIndex; i >= endIndex; i--) - if (_list[i] == null) - return i; - return -1; - } else { - for(int i=startIndex; i >= endIndex; i--) - if (_list[i] != null && _list[i].Equals(value)) - return i; - return -1; - } - } - - public override void Remove(Object value) { - int index = IndexOf(value); - if (index >=0) - RemoveAt(index); - } - - public override void RemoveAt(int index) { - _list.RemoveAt(index); - _version++; - } - - public override void RemoveRange(int index, int count) { - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - Contract.EndContractBlock(); - if (_list.Count - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - - if( count > 0) // be consistent with ArrayList - _version++; - - while(count > 0) { - _list.RemoveAt(index); - count--; - } - } - - public override void Reverse(int index, int count) { - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - Contract.EndContractBlock(); - if (_list.Count - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - - int i = index; - int j = index + count - 1; - while (i < j) - { - Object tmp = _list[i]; - _list[i++] = _list[j]; - _list[j--] = tmp; - } - _version++; - } - - public override void SetRange(int index, ICollection c) { - if (c==null) { - throw new ArgumentNullException(nameof(c), Environment.GetResourceString("ArgumentNull_Collection")); - } - Contract.EndContractBlock(); - - if (index < 0 || index > _list.Count - c.Count) { - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); - } - - if( c.Count > 0) { - IEnumerator en = c.GetEnumerator(); - while(en.MoveNext()) { - _list[index++] = en.Current; - } - _version++; - } - } - - public override ArrayList GetRange(int index, int count) { - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - Contract.EndContractBlock(); - if (_list.Count - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - return new Range(this,index, count); - } - - public override void Sort(int index, int count, IComparer comparer) { - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - Contract.EndContractBlock(); - if (_list.Count - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - - Object [] array = new Object[count]; - CopyTo(index, array, 0, count); - Array.Sort(array, 0, count, comparer); - for(int i=0; i<count; i++) - _list[i+index] = array[i]; - - _version++; - } - - - public override Object[] ToArray() { - Object[] array = new Object[Count]; - _list.CopyTo(array, 0); - return array; - } - - public override Array ToArray(Type type) - { - if (type==null) - throw new ArgumentNullException(nameof(type)); - Contract.EndContractBlock(); - Array array = Array.UnsafeCreateInstance(type, _list.Count); - _list.CopyTo(array, 0); - return array; - } - - public override void TrimToSize() - { - // Can't really do much here... - } - - // This is the enumerator for an IList that's been wrapped in another - // class that implements all of ArrayList's methods. - [Serializable] - private sealed class IListWrapperEnumWrapper : IEnumerator, ICloneable - { - private IEnumerator _en; - private int _remaining; - private int _initialStartIndex; // for reset - private int _initialCount; // for reset - private bool _firstCall; // firstCall to MoveNext - - private IListWrapperEnumWrapper() - { - } - - internal IListWrapperEnumWrapper(IListWrapper listWrapper, int startIndex, int count) - { - _en = listWrapper.GetEnumerator(); - _initialStartIndex = startIndex; - _initialCount = count; - while(startIndex-- > 0 && _en.MoveNext()); - _remaining = count; - _firstCall = true; - } - - public Object Clone() { - // We must clone the underlying enumerator, I think. - IListWrapperEnumWrapper clone = new IListWrapperEnumWrapper(); - clone._en = (IEnumerator) ((ICloneable)_en).Clone(); - clone._initialStartIndex = _initialStartIndex; - clone._initialCount = _initialCount; - clone._remaining = _remaining; - clone._firstCall = _firstCall; - return clone; - } - - public bool MoveNext() { - if (_firstCall) { - _firstCall = false; - return _remaining-- > 0 && _en.MoveNext(); - } - if (_remaining < 0) - return false; - bool r = _en.MoveNext(); - return r && _remaining-- > 0; - } - - public Object Current { - get { - if (_firstCall) - throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted)); - if (_remaining < 0) - throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded)); - return _en.Current; - } - } - - public void Reset() { - _en.Reset(); - int startIndex = _initialStartIndex; - while(startIndex-- > 0 && _en.MoveNext()); - _remaining = _initialCount; - _firstCall = true; - } - } - } - - - [Serializable] - private class SyncArrayList : ArrayList - { - private ArrayList _list; - private Object _root; - - internal SyncArrayList(ArrayList list) - : base( false ) - { - _list = list; - _root = list.SyncRoot; - } - - public override int Capacity { - get { - lock(_root) { - return _list.Capacity; - } - } - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - set { - lock(_root) { - _list.Capacity = value; - } - } - } - - public override int Count { - get { lock(_root) { return _list.Count; } } - } - - public override bool IsReadOnly { - get { return _list.IsReadOnly; } - } - - public override bool IsFixedSize { - get { return _list.IsFixedSize; } - } - - - public override bool IsSynchronized { - get { return true; } - } - - public override Object this[int index] { - get { - lock(_root) { - return _list[index]; - } - } - set { - lock(_root) { - _list[index] = value; - } - } - } - - public override Object SyncRoot { - get { return _root; } - } - - public override int Add(Object value) { - lock(_root) { - return _list.Add(value); - } - } - - public override void AddRange(ICollection c) { - lock(_root) { - _list.AddRange(c); - } - } - - public override int BinarySearch(Object value) { - lock(_root) { - return _list.BinarySearch(value); - } - } - - public override int BinarySearch(Object value, IComparer comparer) { - lock(_root) { - return _list.BinarySearch(value, comparer); - } - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int BinarySearch(int index, int count, Object value, IComparer comparer) { - lock(_root) { - return _list.BinarySearch(index, count, value, comparer); - } - } - - public override void Clear() { - lock(_root) { - _list.Clear(); - } - } - - public override Object Clone() { - lock(_root) { - return new SyncArrayList((ArrayList)_list.Clone()); - } - } - - public override bool Contains(Object item) { - lock(_root) { - return _list.Contains(item); - } - } - - public override void CopyTo(Array array) { - lock(_root) { - _list.CopyTo(array); - } - } - - public override void CopyTo(Array array, int index) { - lock(_root) { - _list.CopyTo(array, index); - } - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void CopyTo(int index, Array array, int arrayIndex, int count) { - lock(_root) { - _list.CopyTo(index, array, arrayIndex, count); - } - } - - public override IEnumerator GetEnumerator() { - lock(_root) { - return _list.GetEnumerator(); - } - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override IEnumerator GetEnumerator(int index, int count) { - lock(_root) { - return _list.GetEnumerator(index, count); - } - } - - public override int IndexOf(Object value) { - lock(_root) { - return _list.IndexOf(value); - } - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int IndexOf(Object value, int startIndex) { - lock(_root) { - return _list.IndexOf(value, startIndex); - } - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int IndexOf(Object value, int startIndex, int count) { - lock(_root) { - return _list.IndexOf(value, startIndex, count); - } - } - - public override void Insert(int index, Object value) { - lock(_root) { - _list.Insert(index, value); - } - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void InsertRange(int index, ICollection c) { - lock(_root) { - _list.InsertRange(index, c); - } - } - - public override int LastIndexOf(Object value) { - lock(_root) { - return _list.LastIndexOf(value); - } - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int LastIndexOf(Object value, int startIndex) { - lock(_root) { - return _list.LastIndexOf(value, startIndex); - } - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int LastIndexOf(Object value, int startIndex, int count) { - lock(_root) { - return _list.LastIndexOf(value, startIndex, count); - } - } - - public override void Remove(Object value) { - lock(_root) { - _list.Remove(value); - } - } - - public override void RemoveAt(int index) { - lock(_root) { - _list.RemoveAt(index); - } - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void RemoveRange(int index, int count) { - lock(_root) { - _list.RemoveRange(index, count); - } - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void Reverse(int index, int count) { - lock(_root) { - _list.Reverse(index, count); - } - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void SetRange(int index, ICollection c) { - lock(_root) { - _list.SetRange(index, c); - } - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override ArrayList GetRange(int index, int count) { - lock(_root) { - return _list.GetRange(index, count); - } - } - - public override void Sort() { - lock(_root) { - _list.Sort(); - } - } - - public override void Sort(IComparer comparer) { - lock(_root) { - _list.Sort(comparer); - } - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void Sort(int index, int count, IComparer comparer) { - lock(_root) { - _list.Sort(index, count, comparer); - } - } - - public override Object[] ToArray() { - lock(_root) { - return _list.ToArray(); - } - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override Array ToArray(Type type) { - lock(_root) { - return _list.ToArray(type); - } - } - - public override void TrimToSize() { - lock(_root) { - _list.TrimToSize(); - } - } - } - - - [Serializable] - private class SyncIList : IList - { - private IList _list; - private Object _root; - - internal SyncIList(IList list) { - _list = list; - _root = list.SyncRoot; - } - - public virtual int Count { - get { lock(_root) { return _list.Count; } } - } - - public virtual bool IsReadOnly { - get { return _list.IsReadOnly; } - } - - public virtual bool IsFixedSize { - get { return _list.IsFixedSize; } - } - - - public virtual bool IsSynchronized { - get { return true; } - } - - public virtual Object this[int index] { - get { - lock(_root) { - return _list[index]; - } - } - set { - lock(_root) { - _list[index] = value; - } - } - } - - public virtual Object SyncRoot { - get { return _root; } - } - - public virtual int Add(Object value) { - lock(_root) { - return _list.Add(value); - } - } - - - public virtual void Clear() { - lock(_root) { - _list.Clear(); - } - } - - public virtual bool Contains(Object item) { - lock(_root) { - return _list.Contains(item); - } - } - - public virtual void CopyTo(Array array, int index) { - lock(_root) { - _list.CopyTo(array, index); - } - } - - public virtual IEnumerator GetEnumerator() { - lock(_root) { - return _list.GetEnumerator(); - } - } - - public virtual int IndexOf(Object value) { - lock(_root) { - return _list.IndexOf(value); - } - } - - public virtual void Insert(int index, Object value) { - lock(_root) { - _list.Insert(index, value); - } - } - - public virtual void Remove(Object value) { - lock(_root) { - _list.Remove(value); - } - } - - public virtual void RemoveAt(int index) { - lock(_root) { - _list.RemoveAt(index); - } - } - } - - [Serializable] - private class FixedSizeList : IList - { - private IList _list; - - internal FixedSizeList(IList l) { - _list = l; - } - - public virtual int Count { - get { return _list.Count; } - } - - public virtual bool IsReadOnly { - get { return _list.IsReadOnly; } - } - - public virtual bool IsFixedSize { - get { return true; } - } - - public virtual bool IsSynchronized { - get { return _list.IsSynchronized; } - } - - public virtual Object this[int index] { - get { - return _list[index]; - } - set { - _list[index] = value; - } - } - - public virtual Object SyncRoot { - get { return _list.SyncRoot; } - } - - public virtual int Add(Object obj) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); - } - - public virtual void Clear() { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); - } - - public virtual bool Contains(Object obj) { - return _list.Contains(obj); - } - - public virtual void CopyTo(Array array, int index) { - _list.CopyTo(array, index); - } - - public virtual IEnumerator GetEnumerator() { - return _list.GetEnumerator(); - } - - public virtual int IndexOf(Object value) { - return _list.IndexOf(value); - } - - public virtual void Insert(int index, Object obj) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); - } - - public virtual void Remove(Object value) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); - } - - public virtual void RemoveAt(int index) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); - } - } - - [Serializable] - private class FixedSizeArrayList : ArrayList - { - private ArrayList _list; - - internal FixedSizeArrayList(ArrayList l) { - _list = l; - _version = _list._version; - } - - public override int Count { - get { return _list.Count; } - } - - public override bool IsReadOnly { - get { return _list.IsReadOnly; } - } - - public override bool IsFixedSize { - get { return true; } - } - - public override bool IsSynchronized { - get { return _list.IsSynchronized; } - } - - public override Object this[int index] { - get { - return _list[index]; - } - set { - _list[index] = value; - _version = _list._version; - } - } - - public override Object SyncRoot { - get { return _list.SyncRoot; } - } - - public override int Add(Object obj) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); - } - - public override void AddRange(ICollection c) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int BinarySearch(int index, int count, Object value, IComparer comparer) { - return _list.BinarySearch(index, count, value, comparer); - } - - public override int Capacity { - get { return _list.Capacity; } - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - set { throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); } - } - - public override void Clear() { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); - } - - public override Object Clone() { - FixedSizeArrayList arrayList = new FixedSizeArrayList(_list); - arrayList._list = (ArrayList)_list.Clone(); - return arrayList; - } - - public override bool Contains(Object obj) { - return _list.Contains(obj); - } - - public override void CopyTo(Array array, int index) { - _list.CopyTo(array, index); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void CopyTo(int index, Array array, int arrayIndex, int count) { - _list.CopyTo(index, array, arrayIndex, count); - } - - public override IEnumerator GetEnumerator() { - return _list.GetEnumerator(); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override IEnumerator GetEnumerator(int index, int count) { - return _list.GetEnumerator(index, count); - } - - public override int IndexOf(Object value) { - return _list.IndexOf(value); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int IndexOf(Object value, int startIndex) { - return _list.IndexOf(value, startIndex); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int IndexOf(Object value, int startIndex, int count) { - return _list.IndexOf(value, startIndex, count); - } - - public override void Insert(int index, Object obj) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void InsertRange(int index, ICollection c) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); - } - - public override int LastIndexOf(Object value) { - return _list.LastIndexOf(value); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int LastIndexOf(Object value, int startIndex) { - return _list.LastIndexOf(value, startIndex); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int LastIndexOf(Object value, int startIndex, int count) { - return _list.LastIndexOf(value, startIndex, count); - } - - public override void Remove(Object value) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); - } - - public override void RemoveAt(int index) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void RemoveRange(int index, int count) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void SetRange(int index, ICollection c) { - _list.SetRange(index, c); - _version = _list._version; - } - - public override ArrayList GetRange(int index, int count) { - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (Count - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - return new Range(this,index, count); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void Reverse(int index, int count) { - _list.Reverse(index, count); - _version = _list._version; - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void Sort(int index, int count, IComparer comparer) { - _list.Sort(index, count, comparer); - _version = _list._version; - } - - public override Object[] ToArray() { - return _list.ToArray(); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override Array ToArray(Type type) { - return _list.ToArray(type); - } - - public override void TrimToSize() { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); - } - } - [Serializable] private class ReadOnlyList : IList { @@ -1908,626 +459,6 @@ namespace System.Collections { } [Serializable] - private class ReadOnlyArrayList : ArrayList - { - private ArrayList _list; - - internal ReadOnlyArrayList(ArrayList l) { - _list = l; - } - - public override int Count { - get { return _list.Count; } - } - - public override bool IsReadOnly { - get { return true; } - } - - public override bool IsFixedSize { - get { return true; } - } - - public override bool IsSynchronized { - get { return _list.IsSynchronized; } - } - - public override Object this[int index] { - get { - return _list[index]; - } - set { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection")); - } - } - - public override Object SyncRoot { - get { return _list.SyncRoot; } - } - - public override int Add(Object obj) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection")); - } - - public override void AddRange(ICollection c) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection")); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int BinarySearch(int index, int count, Object value, IComparer comparer) { - return _list.BinarySearch(index, count, value, comparer); - } - - - public override int Capacity { - get { return _list.Capacity; } - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - set { throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection")); } - } - - public override void Clear() { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection")); - } - - public override Object Clone() { - ReadOnlyArrayList arrayList = new ReadOnlyArrayList(_list); - arrayList._list = (ArrayList)_list.Clone(); - return arrayList; - } - - public override bool Contains(Object obj) { - return _list.Contains(obj); - } - - public override void CopyTo(Array array, int index) { - _list.CopyTo(array, index); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void CopyTo(int index, Array array, int arrayIndex, int count) { - _list.CopyTo(index, array, arrayIndex, count); - } - - public override IEnumerator GetEnumerator() { - return _list.GetEnumerator(); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override IEnumerator GetEnumerator(int index, int count) { - return _list.GetEnumerator(index, count); - } - - public override int IndexOf(Object value) { - return _list.IndexOf(value); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int IndexOf(Object value, int startIndex) { - return _list.IndexOf(value, startIndex); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int IndexOf(Object value, int startIndex, int count) { - return _list.IndexOf(value, startIndex, count); - } - - public override void Insert(int index, Object obj) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection")); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void InsertRange(int index, ICollection c) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection")); - } - - public override int LastIndexOf(Object value) { - return _list.LastIndexOf(value); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int LastIndexOf(Object value, int startIndex) { - return _list.LastIndexOf(value, startIndex); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int LastIndexOf(Object value, int startIndex, int count) { - return _list.LastIndexOf(value, startIndex, count); - } - - public override void Remove(Object value) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection")); - } - - public override void RemoveAt(int index) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection")); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void RemoveRange(int index, int count) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection")); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void SetRange(int index, ICollection c) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection")); - } - - public override ArrayList GetRange(int index, int count) { - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (Count - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - return new Range(this,index, count); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void Reverse(int index, int count) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection")); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void Sort(int index, int count, IComparer comparer) { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection")); - } - - public override Object[] ToArray() { - return _list.ToArray(); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override Array ToArray(Type type) { - return _list.ToArray(type); - } - - public override void TrimToSize() { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection")); - } - } - - - // Implements an enumerator for a ArrayList. The enumerator uses the - // internal version number of the list to ensure that no modifications are - // made to the list while an enumeration is in progress. - [Serializable] - private sealed class ArrayListEnumerator : IEnumerator, ICloneable - { - private ArrayList list; - private int index; - private int endIndex; // Where to stop. - private int version; - private Object currentElement; - private int startIndex; // Save this for Reset. - - internal ArrayListEnumerator(ArrayList list, int index, int count) { - this.list = list; - startIndex = index; - this.index = index - 1; - endIndex = this.index + count; // last valid index - version = list._version; - currentElement = null; - } - - public Object Clone() { - return MemberwiseClone(); - } - - public bool MoveNext() { - if (version != list._version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion)); - if (index < endIndex) { - currentElement = list[++index]; - return true; - } - else { - index = endIndex + 1; - } - - return false; - } - - public Object Current { - get { - if (index < startIndex) - throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted)); - else if (index > endIndex) { - throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded)); - } - return currentElement; - } - } - - public void Reset() { - if (version != list._version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion)); - index = startIndex - 1; - } - } - - // Implementation of a generic list subrange. An instance of this class - // is returned by the default implementation of List.GetRange. - [Serializable] - private class Range: ArrayList - { - private ArrayList _baseList; - private int _baseIndex; - [ContractPublicPropertyName("Count")] - private int _baseSize; - private int _baseVersion; - - internal Range(ArrayList list, int index, int count) : base(false) { - _baseList = list; - _baseIndex = index; - _baseSize = count; - _baseVersion = list._version; - // we also need to update _version field to make Range of Range work - _version = list._version; - } - - private void InternalUpdateRange() - { - if (_baseVersion != _baseList._version) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnderlyingArrayListChanged")); - } - - private void InternalUpdateVersion() { - _baseVersion++; - _version++; - } - - public override int Add(Object value) { - InternalUpdateRange(); - _baseList.Insert(_baseIndex + _baseSize, value); - InternalUpdateVersion(); - return _baseSize++; - } - - public override void AddRange(ICollection c) { - if( c == null ) { - throw new ArgumentNullException(nameof(c)); - } - Contract.EndContractBlock(); - - InternalUpdateRange(); - int count = c.Count; - if( count > 0) { - _baseList.InsertRange(_baseIndex + _baseSize, c); - InternalUpdateVersion(); - _baseSize += count; - } - } - - // Other overloads with automatically work - public override int BinarySearch(int index, int count, Object value, IComparer comparer) { - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (_baseSize - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - InternalUpdateRange(); - - int i = _baseList.BinarySearch(_baseIndex + index, count, value, comparer); - if (i >= 0) return i - _baseIndex; - return i + _baseIndex; - } - - public override int Capacity { - get { - return _baseList.Capacity; - } - - set { - if (value < Count) throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity")); - Contract.EndContractBlock(); - } - } - - - public override void Clear() { - InternalUpdateRange(); - if (_baseSize != 0) - { - _baseList.RemoveRange(_baseIndex, _baseSize); - InternalUpdateVersion(); - _baseSize = 0; - } - } - - public override Object Clone() { - InternalUpdateRange(); - Range arrayList = new Range(_baseList,_baseIndex,_baseSize); - arrayList._baseList = (ArrayList)_baseList.Clone(); - return arrayList; - } - - public override bool Contains(Object item) { - InternalUpdateRange(); - if (item==null) { - for(int i=0; i<_baseSize; i++) - if (_baseList[_baseIndex + i]==null) - return true; - return false; - } - else { - for(int i=0; i<_baseSize; i++) - if (_baseList[_baseIndex + i] != null && _baseList[_baseIndex + i].Equals(item)) - return true; - return false; - } - } - - public override void CopyTo(Array array, int index) { - if (array==null) - throw new ArgumentNullException(nameof(array)); - if (array.Rank != 1) - throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported")); - if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (array.Length - index < _baseSize) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - InternalUpdateRange(); - _baseList.CopyTo(_baseIndex, array, index, _baseSize); - } - - public override void CopyTo(int index, Array array, int arrayIndex, int count) { - if (array==null) - throw new ArgumentNullException(nameof(array)); - if (array.Rank != 1) - throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported")); - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (array.Length - arrayIndex < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - if (_baseSize - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - InternalUpdateRange(); - _baseList.CopyTo(_baseIndex + index, array, arrayIndex, count); - } - - public override int Count { - get { - InternalUpdateRange(); - return _baseSize; - } - } - - public override bool IsReadOnly { - get { return _baseList.IsReadOnly; } - } - - public override bool IsFixedSize { - get { return _baseList.IsFixedSize; } - } - - public override bool IsSynchronized { - get { return _baseList.IsSynchronized; } - } - - public override IEnumerator GetEnumerator() { - return GetEnumerator(0,_baseSize); - } - - public override IEnumerator GetEnumerator(int index, int count) { - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (_baseSize - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - InternalUpdateRange(); - return _baseList.GetEnumerator(_baseIndex + index, count); - } - - public override ArrayList GetRange(int index, int count) { - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (_baseSize - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - InternalUpdateRange(); - return new Range(this, index, count); - } - - public override Object SyncRoot { - get { - return _baseList.SyncRoot; - } - } - - - public override int IndexOf(Object value) { - InternalUpdateRange(); - int i = _baseList.IndexOf(value, _baseIndex, _baseSize); - if (i >= 0) return i - _baseIndex; - return -1; - } - - public override int IndexOf(Object value, int startIndex) { - if (startIndex < 0) - throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (startIndex > _baseSize) - throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); - Contract.EndContractBlock(); - - InternalUpdateRange(); - int i = _baseList.IndexOf(value, _baseIndex + startIndex, _baseSize - startIndex); - if (i >= 0) return i - _baseIndex; - return -1; - } - - public override int IndexOf(Object value, int startIndex, int count) { - if (startIndex < 0 || startIndex > _baseSize) - throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); - - if (count < 0 || (startIndex > _baseSize - count)) - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count")); - Contract.EndContractBlock(); - - InternalUpdateRange(); - int i = _baseList.IndexOf(value, _baseIndex + startIndex, count); - if (i >= 0) return i - _baseIndex; - return -1; - } - - public override void Insert(int index, Object value) { - if (index < 0 || index > _baseSize) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); - Contract.EndContractBlock(); - - InternalUpdateRange(); - _baseList.Insert(_baseIndex + index, value); - InternalUpdateVersion(); - _baseSize++; - } - - public override void InsertRange(int index, ICollection c) { - if (index < 0 || index > _baseSize) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); - if( c == null) { - throw new ArgumentNullException(nameof(c)); - } - Contract.EndContractBlock(); - - InternalUpdateRange(); - int count = c.Count; - if( count > 0) { - _baseList.InsertRange(_baseIndex + index, c); - _baseSize += count; - InternalUpdateVersion(); - } - } - - public override int LastIndexOf(Object value) { - InternalUpdateRange(); - int i = _baseList.LastIndexOf(value, _baseIndex + _baseSize - 1, _baseSize); - if (i >= 0) return i - _baseIndex; - return -1; - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int LastIndexOf(Object value, int startIndex) { - return LastIndexOf(value, startIndex, startIndex + 1); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override int LastIndexOf(Object value, int startIndex, int count) { - InternalUpdateRange(); - if (_baseSize == 0) - return -1; - - if (startIndex >= _baseSize) - throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index")); - if (startIndex < 0) - throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - - int i = _baseList.LastIndexOf(value, _baseIndex + startIndex, count); - if (i >= 0) return i - _baseIndex; - return -1; - } - - // Don't need to override Remove - - public override void RemoveAt(int index) { - if (index < 0 || index >= _baseSize) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); - Contract.EndContractBlock(); - - InternalUpdateRange(); - _baseList.RemoveAt(_baseIndex + index); - InternalUpdateVersion(); - _baseSize--; - } - - public override void RemoveRange(int index, int count) { - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (_baseSize - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - InternalUpdateRange(); - // No need to call _bastList.RemoveRange if count is 0. - // In addition, _baseList won't change the vresion number if count is 0. - if( count > 0) { - _baseList.RemoveRange(_baseIndex + index, count); - InternalUpdateVersion(); - _baseSize -= count; - } - } - - public override void Reverse(int index, int count) { - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (_baseSize - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - InternalUpdateRange(); - _baseList.Reverse(_baseIndex + index, count); - InternalUpdateVersion(); - } - - [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems. - public override void SetRange(int index, ICollection c) { - InternalUpdateRange(); - if (index < 0 || index >= _baseSize) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); - _baseList.SetRange(_baseIndex + index, c); - if( c.Count > 0) { - InternalUpdateVersion(); - } - } - - public override void Sort(int index, int count, IComparer comparer) { - if (index < 0 || count < 0) - throw new ArgumentOutOfRangeException((index<0 ? nameof(index) : nameof(count)), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (_baseSize - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - InternalUpdateRange(); - _baseList.Sort(_baseIndex + index, count, comparer); - InternalUpdateVersion(); - } - - public override Object this[int index] { - get { - InternalUpdateRange(); - if (index < 0 || index >= _baseSize) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); - return _baseList[_baseIndex + index]; - } - set { - InternalUpdateRange(); - if (index < 0 || index >= _baseSize) throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index")); - _baseList[_baseIndex + index] = value; - InternalUpdateVersion(); - } - } - - public override Object[] ToArray() { - InternalUpdateRange(); - Object[] array = new Object[_baseSize]; - Array.Copy(_baseList._items, _baseIndex, array, 0, _baseSize); - return array; - } - - public override Array ToArray(Type type) { - if (type==null) - throw new ArgumentNullException(nameof(type)); - Contract.EndContractBlock(); - - InternalUpdateRange(); - Array array = Array.UnsafeCreateInstance(type, _baseSize); - _baseList.CopyTo(_baseIndex, array, 0, _baseSize); - return array; - } - - public override void TrimToSize() { - throw new NotSupportedException(Environment.GetResourceString("NotSupported_RangeCollection")); - } - } - - [Serializable] private sealed class ArrayListEnumeratorSimple : IEnumerator, ICloneable { private ArrayList list; private int index; @@ -2607,20 +538,6 @@ namespace System.Collections { internal class ArrayListDebugView { private ArrayList arrayList; - - public ArrayListDebugView( ArrayList arrayList) { - if( arrayList == null) - throw new ArgumentNullException(nameof(arrayList)); - - this.arrayList = arrayList; - } - - [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] - public Object[] Items { - get { - return arrayList.ToArray(); - } - } } } } diff --git a/src/mscorlib/src/System/Collections/CollectionBase.cs b/src/mscorlib/src/System/Collections/CollectionBase.cs index ae0c0d302d..a3dd88a7b3 100644 --- a/src/mscorlib/src/System/Collections/CollectionBase.cs +++ b/src/mscorlib/src/System/Collections/CollectionBase.cs @@ -12,20 +12,14 @@ namespace System.Collections { // Useful base class for typed read/write collections where items derive from object [Serializable] -[System.Runtime.InteropServices.ComVisible(true)] public abstract class CollectionBase : IList { - ArrayList list; + private ArrayList list; protected CollectionBase() { list = new ArrayList(); } - - protected CollectionBase(int capacity) { - list = new ArrayList(capacity); - } - - protected ArrayList InnerList { + internal ArrayList InnerList { get { if (list == null) list = new ArrayList(); @@ -37,16 +31,6 @@ namespace System.Collections { get { return (IList)this; } } - [System.Runtime.InteropServices.ComVisible(false)] - public int Capacity { - get { - return InnerList.Capacity; - } - set { - InnerList.Capacity = value; - } - } - public int Count { get { diff --git a/src/mscorlib/src/System/Collections/Comparer.cs b/src/mscorlib/src/System/Collections/Comparer.cs index 0e3c78b529..928b0f9f9a 100644 --- a/src/mscorlib/src/System/Collections/Comparer.cs +++ b/src/mscorlib/src/System/Collections/Comparer.cs @@ -17,12 +17,10 @@ namespace System.Collections { using System; using System.Globalization; using System.Runtime.Serialization; - using System.Security.Permissions; using System.Diagnostics.Contracts; [Serializable] - [System.Runtime.InteropServices.ComVisible(true)] - public sealed class Comparer : IComparer , ISerializable + internal sealed class Comparer : IComparer , ISerializable { private CompareInfo m_compareInfo; public static readonly Comparer Default = new Comparer(CultureInfo.CurrentCulture); diff --git a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs index c1a6f7564c..8b9014a103 100644 --- a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs +++ b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs @@ -24,7 +24,6 @@ using System.Runtime.Serialization; using System.Text; using System.Threading; using System.Security; -using System.Security.Permissions; namespace System.Collections.Concurrent { @@ -37,10 +36,9 @@ namespace System.Collections.Concurrent /// All public and protected members of <see cref="ConcurrentDictionary{TKey,TValue}"/> are thread-safe and may be used /// concurrently from multiple threads. /// </remarks> - [ComVisible(false)] [DebuggerTypeProxy(typeof(Mscorlib_DictionaryDebugView<,>))] [DebuggerDisplay("Count = {Count}")] - public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary, IReadOnlyDictionary<TKey, TValue> + internal class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary, IReadOnlyDictionary<TKey, TValue> { /// <summary> /// Tables that hold the internal state of the ConcurrentDictionary @@ -139,149 +137,6 @@ namespace System.Collections.Concurrent /// </summary> public ConcurrentDictionary() : this(DefaultConcurrencyLevel, DEFAULT_CAPACITY, true, EqualityComparer<TKey>.Default) { } - /// <summary> - /// Initializes a new instance of the <see - /// cref="ConcurrentDictionary{TKey,TValue}"/> - /// class that is empty, has the specified concurrency level and capacity, and uses the default - /// comparer for the key type. - /// </summary> - /// <param name="concurrencyLevel">The estimated number of threads that will update the - /// <see cref="ConcurrentDictionary{TKey,TValue}"/> concurrently.</param> - /// <param name="capacity">The initial number of elements that the <see - /// cref="ConcurrentDictionary{TKey,TValue}"/> - /// can contain.</param> - /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="concurrencyLevel"/> is - /// less than 1.</exception> - /// <exception cref="T:System.ArgumentOutOfRangeException"> <paramref name="capacity"/> is less than - /// 0.</exception> - public ConcurrentDictionary(int concurrencyLevel, int capacity) : this(concurrencyLevel, capacity, false, EqualityComparer<TKey>.Default) { } - - /// <summary> - /// Initializes a new instance of the <see cref="ConcurrentDictionary{TKey,TValue}"/> - /// class that contains elements copied from the specified <see - /// cref="T:System.Collections.IEnumerable{KeyValuePair{TKey,TValue}}"/>, has the default concurrency - /// level, has the default initial capacity, and uses the default comparer for the key type. - /// </summary> - /// <param name="collection">The <see - /// cref="T:System.Collections.IEnumerable{KeyValuePair{TKey,TValue}}"/> whose elements are copied to - /// the new - /// <see cref="ConcurrentDictionary{TKey,TValue}"/>.</param> - /// <exception cref="T:System.ArgumentNullException"><paramref name="collection"/> is a null reference - /// (Nothing in Visual Basic).</exception> - /// <exception cref="T:System.ArgumentException"><paramref name="collection"/> contains one or more - /// duplicate keys.</exception> - public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection) : this(collection, EqualityComparer<TKey>.Default) { } - - /// <summary> - /// Initializes a new instance of the <see cref="ConcurrentDictionary{TKey,TValue}"/> - /// class that is empty, has the specified concurrency level and capacity, and uses the specified - /// <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/>. - /// </summary> - /// <param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/> - /// implementation to use when comparing keys.</param> - /// <exception cref="T:System.ArgumentNullException"><paramref name="comparer"/> is a null reference - /// (Nothing in Visual Basic).</exception> - public ConcurrentDictionary(IEqualityComparer<TKey> comparer) : this(DefaultConcurrencyLevel, DEFAULT_CAPACITY, true, comparer) { } - - /// <summary> - /// Initializes a new instance of the <see cref="ConcurrentDictionary{TKey,TValue}"/> - /// class that contains elements copied from the specified <see - /// cref="T:System.Collections.IEnumerable"/>, has the default concurrency level, has the default - /// initial capacity, and uses the specified - /// <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/>. - /// </summary> - /// <param name="collection">The <see - /// cref="T:System.Collections.IEnumerable{KeyValuePair{TKey,TValue}}"/> whose elements are copied to - /// the new - /// <see cref="ConcurrentDictionary{TKey,TValue}"/>.</param> - /// <param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/> - /// implementation to use when comparing keys.</param> - /// <exception cref="T:System.ArgumentNullException"><paramref name="collection"/> is a null reference - /// (Nothing in Visual Basic). -or- - /// <paramref name="comparer"/> is a null reference (Nothing in Visual Basic). - /// </exception> - public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer) - : this(comparer) - { - if (collection == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); - - InitializeFromCollection(collection); - } - - /// <summary> - /// Initializes a new instance of the <see cref="ConcurrentDictionary{TKey,TValue}"/> - /// class that contains elements copied from the specified <see cref="T:System.Collections.IEnumerable"/>, - /// has the specified concurrency level, has the specified initial capacity, and uses the specified - /// <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/>. - /// </summary> - /// <param name="concurrencyLevel">The estimated number of threads that will update the - /// <see cref="ConcurrentDictionary{TKey,TValue}"/> concurrently.</param> - /// <param name="collection">The <see cref="T:System.Collections.IEnumerable{KeyValuePair{TKey,TValue}}"/> whose elements are copied to the new - /// <see cref="ConcurrentDictionary{TKey,TValue}"/>.</param> - /// <param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/> implementation to use - /// when comparing keys.</param> - /// <exception cref="T:System.ArgumentNullException"> - /// <paramref name="collection"/> is a null reference (Nothing in Visual Basic). - /// -or- - /// <paramref name="comparer"/> is a null reference (Nothing in Visual Basic). - /// </exception> - /// <exception cref="T:System.ArgumentOutOfRangeException"> - /// <paramref name="concurrencyLevel"/> is less than 1. - /// </exception> - /// <exception cref="T:System.ArgumentException"><paramref name="collection"/> contains one or more duplicate keys.</exception> - public ConcurrentDictionary( - int concurrencyLevel, IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer) - : this(concurrencyLevel, DEFAULT_CAPACITY, false, comparer) - { - if (collection == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); - if (comparer == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparer); - - InitializeFromCollection(collection); - } - - private void InitializeFromCollection(IEnumerable<KeyValuePair<TKey, TValue>> collection) - { - TValue dummy; - foreach (KeyValuePair<TKey, TValue> pair in collection) - { - if (pair.Key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); - - if (!TryAddInternal(pair.Key, pair.Value, false, false, out dummy)) - { - ThrowHelper.ThrowArgumentException(ExceptionResource.ConcurrentDictionary_SourceContainsDuplicateKeys); - } - } - - if (m_budget == 0) - { - m_budget = m_tables.m_buckets.Length / m_tables.m_locks.Length; - } - - } - - /// <summary> - /// Initializes a new instance of the <see cref="ConcurrentDictionary{TKey,TValue}"/> - /// class that is empty, has the specified concurrency level, has the specified initial capacity, and - /// uses the specified <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/>. - /// </summary> - /// <param name="concurrencyLevel">The estimated number of threads that will update the - /// <see cref="ConcurrentDictionary{TKey,TValue}"/> concurrently.</param> - /// <param name="capacity">The initial number of elements that the <see - /// cref="ConcurrentDictionary{TKey,TValue}"/> - /// can contain.</param> - /// <param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/> - /// implementation to use when comparing keys.</param> - /// <exception cref="T:System.ArgumentOutOfRangeException"> - /// <paramref name="concurrencyLevel"/> is less than 1. -or- - /// <paramref name="capacity"/> is less than 0. - /// </exception> - /// <exception cref="T:System.ArgumentNullException"><paramref name="comparer"/> is a null reference - /// (Nothing in Visual Basic).</exception> - public ConcurrentDictionary(int concurrencyLevel, int capacity, IEqualityComparer<TKey> comparer) - : this(concurrencyLevel, capacity, false, comparer) - { - } - internal ConcurrentDictionary(int concurrencyLevel, int capacity, bool growLockArray, IEqualityComparer<TKey> comparer) { if (concurrencyLevel < 1) @@ -488,91 +343,6 @@ namespace System.Collections.Concurrent } /// <summary> - /// Compares the existing value for the specified key with a specified value, and if they're equal, - /// updates the key with a third value. - /// </summary> - /// <param name="key">The key whose value is compared with <paramref name="comparisonValue"/> and - /// possibly replaced.</param> - /// <param name="newValue">The value that replaces the value of the element with <paramref - /// name="key"/> if the comparison results in equality.</param> - /// <param name="comparisonValue">The value that is compared to the value of the element with - /// <paramref name="key"/>.</param> - /// <returns>true if the value with <paramref name="key"/> was equal to <paramref - /// name="comparisonValue"/> and replaced with <paramref name="newValue"/>; otherwise, - /// false.</returns> - /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null - /// reference.</exception> - [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")] - public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue) - { - if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); - - IEqualityComparer<TValue> valueComparer = EqualityComparer<TValue>.Default; - - while (true) - { - int bucketNo; - int lockNo; - int hashcode; - - Tables tables = m_tables; - IEqualityComparer<TKey> comparer = tables.m_comparer; - - hashcode = comparer.GetHashCode(key); - GetBucketAndLockNo(hashcode, out bucketNo, out lockNo, tables.m_buckets.Length, tables.m_locks.Length); - - lock (tables.m_locks[lockNo]) - { - // If the table just got resized, we may not be holding the right lock, and must retry. - // This should be a rare occurence. - if (tables != m_tables) - { - continue; - } - - // Try to find this key in the bucket - Node prev = null; - for (Node node = tables.m_buckets[bucketNo]; node != null; node = node.m_next) - { - Assert((prev == null && node == tables.m_buckets[bucketNo]) || prev.m_next == node); - if (comparer.Equals(node.m_key, key)) - { - if (valueComparer.Equals(node.m_value, comparisonValue)) - { - if (s_isValueWriteAtomic) - { - node.m_value = newValue; - } - else - { - Node newNode = new Node(node.m_key, newValue, hashcode, node.m_next); - - if (prev == null) - { - tables.m_buckets[bucketNo] = newNode; - } - else - { - prev.m_next = newNode; - } - } - - return true; - } - - return false; - } - - prev = node; - } - - //didn't find the key - return false; - } - } - } - - /// <summary> /// Removes all keys and values from the <see cref="ConcurrentDictionary{TKey,TValue}"/>. /// </summary> public void Clear() @@ -947,149 +717,6 @@ namespace System.Collections.Concurrent } } - /// <summary> - /// Adds a key/value pair to the <see cref="ConcurrentDictionary{TKey,TValue}"/> - /// if the key does not already exist. - /// </summary> - /// <param name="key">The key of the element to add.</param> - /// <param name="valueFactory">The function used to generate a value for the key</param> - /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference - /// (Nothing in Visual Basic).</exception> - /// <exception cref="T:System.ArgumentNullException"><paramref name="valueFactory"/> is a null reference - /// (Nothing in Visual Basic).</exception> - /// <exception cref="T:System.OverflowException">The dictionary contains too many - /// elements.</exception> - /// <returns>The value for the key. This will be either the existing value for the key if the - /// key is already in the dictionary, or the new value for the key as returned by valueFactory - /// if the key was not in the dictionary.</returns> - public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory) - { - if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); - if (valueFactory == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.valueFactory); - - TValue resultingValue; - if (TryGetValue(key, out resultingValue)) - { - return resultingValue; - } - TryAddInternal(key, valueFactory(key), false, true, out resultingValue); - return resultingValue; - } - - /// <summary> - /// Adds a key/value pair to the <see cref="ConcurrentDictionary{TKey,TValue}"/> - /// if the key does not already exist. - /// </summary> - /// <param name="key">The key of the element to add.</param> - /// <param name="value">the value to be added, if the key does not already exist</param> - /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference - /// (Nothing in Visual Basic).</exception> - /// <exception cref="T:System.OverflowException">The dictionary contains too many - /// elements.</exception> - /// <returns>The value for the key. This will be either the existing value for the key if the - /// key is already in the dictionary, or the new value if the key was not in the dictionary.</returns> - public TValue GetOrAdd(TKey key, TValue value) - { - if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); - - TValue resultingValue; - TryAddInternal(key, value, false, true, out resultingValue); - return resultingValue; - } - - /// <summary> - /// Adds a key/value pair to the <see cref="ConcurrentDictionary{TKey,TValue}"/> if the key does not already - /// exist, or updates a key/value pair in the <see cref="ConcurrentDictionary{TKey,TValue}"/> if the key - /// already exists. - /// </summary> - /// <param name="key">The key to be added or whose value should be updated</param> - /// <param name="addValueFactory">The function used to generate a value for an absent key</param> - /// <param name="updateValueFactory">The function used to generate a new value for an existing key - /// based on the key's existing value</param> - /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference - /// (Nothing in Visual Basic).</exception> - /// <exception cref="T:System.ArgumentNullException"><paramref name="addValueFactory"/> is a null reference - /// (Nothing in Visual Basic).</exception> - /// <exception cref="T:System.ArgumentNullException"><paramref name="updateValueFactory"/> is a null reference - /// (Nothing in Visual Basic).</exception> - /// <exception cref="T:System.OverflowException">The dictionary contains too many - /// elements.</exception> - /// <returns>The new value for the key. This will be either be the result of addValueFactory (if the key was - /// absent) or the result of updateValueFactory (if the key was present).</returns> - public TValue AddOrUpdate(TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory) - { - if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); - if (addValueFactory == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.addValueFactory); - if (updateValueFactory == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.updateValueFactory); - - TValue newValue, resultingValue; - while (true) - { - TValue oldValue; - if (TryGetValue(key, out oldValue)) - //key exists, try to update - { - newValue = updateValueFactory(key, oldValue); - if (TryUpdate(key, newValue, oldValue)) - { - return newValue; - } - } - else //try add - { - newValue = addValueFactory(key); - if (TryAddInternal(key, newValue, false, true, out resultingValue)) - { - return resultingValue; - } - } - } - } - - /// <summary> - /// Adds a key/value pair to the <see cref="ConcurrentDictionary{TKey,TValue}"/> if the key does not already - /// exist, or updates a key/value pair in the <see cref="ConcurrentDictionary{TKey,TValue}"/> if the key - /// already exists. - /// </summary> - /// <param name="key">The key to be added or whose value should be updated</param> - /// <param name="addValue">The value to be added for an absent key</param> - /// <param name="updateValueFactory">The function used to generate a new value for an existing key based on - /// the key's existing value</param> - /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference - /// (Nothing in Visual Basic).</exception> - /// <exception cref="T:System.ArgumentNullException"><paramref name="updateValueFactory"/> is a null reference - /// (Nothing in Visual Basic).</exception> - /// <exception cref="T:System.OverflowException">The dictionary contains too many - /// elements.</exception> - /// <returns>The new value for the key. This will be either be the result of addValueFactory (if the key was - /// absent) or the result of updateValueFactory (if the key was present).</returns> - public TValue AddOrUpdate(TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory) - { - if (key == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); - if (updateValueFactory == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.updateValueFactory); - TValue newValue, resultingValue; - while (true) - { - TValue oldValue; - if (TryGetValue(key, out oldValue)) - //key exists, try to update - { - newValue = updateValueFactory(key, oldValue); - if (TryUpdate(key, newValue, oldValue)) - { - return newValue; - } - } - else //try add - { - if (TryAddInternal(key, addValue, false, true, out resultingValue)) - { - return resultingValue; - } - } - } - } - /// <summary> diff --git a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentQueue.cs b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentQueue.cs index 7aa5971690..90ada007dd 100644 --- a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentQueue.cs +++ b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentQueue.cs @@ -1,67 +1,100 @@ // 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. -#pragma warning disable 0420 - -// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// -// -// -// A lock-free, concurrent queue primitive, and its associated debugger view type. -// -// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - -using System; -using System.Collections; using System.Collections.Generic; using System.Diagnostics; -using System.Diagnostics.Contracts; -using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Runtime.Serialization; -using System.Security; -using System.Security.Permissions; using System.Threading; namespace System.Collections.Concurrent { - /// <summary> /// Represents a thread-safe first-in, first-out collection of objects. /// </summary> /// <typeparam name="T">Specifies the type of elements in the queue.</typeparam> /// <remarks> - /// All public and protected members of <see cref="ConcurrentQueue{T}"/> are thread-safe and may be used + /// All public and protected members of <see cref="ConcurrentQueue{T}"/> are thread-safe and may be used /// concurrently from multiple threads. /// </remarks> - [ComVisible(false)] [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(SystemCollectionsConcurrent_ProducerConsumerCollectionDebugView<>))] [Serializable] - public class ConcurrentQueue<T> : IProducerConsumerCollection<T>, IReadOnlyCollection<T> + internal class ConcurrentQueue<T> : IProducerConsumerCollection<T>, IReadOnlyCollection<T> { - //fields of ConcurrentQueue - [NonSerialized] - private volatile Segment m_head; + // This implementation provides an unbounded, multi-producer multi-consumer queue + // that supports the standard Enqueue/TryDequeue operations, as well as support for + // snapshot enumeration (GetEnumerator, ToArray, CopyTo), peeking, and Count/IsEmpty. + // It is composed of a linked list of bounded ring buffers, each of which has a head + // and a tail index, isolated from each other to minimize false sharing. As long as + // the number of elements in the queue remains less than the size of the current + // buffer (Segment), no additional allocations are required for enqueued items. When + // the number of items exceeds the size of the current segment, the current segment is + // "frozen" to prevent further enqueues, and a new segment is linked from it and set + // as the new tail segment for subsequent enqueues. As old segments are consumed by + // dequeues, the head reference is updated to point to the segment that dequeuers should + // try next. To support snapshot enumeration, segments also support the notion of + // preserving for observation, whereby they avoid overwriting state as part of dequeues. + // Any operation that requires a snapshot results in all current segments being + // both frozen for enqueues and preserved for observation: any new enqueues will go + // to new segments, and dequeuers will consume from the existing segments but without + // overwriting the existing data. + + /// <summary>Initial length of the segments used in the queue.</summary> + private const int InitialSegmentLength = 32; + /// <summary> + /// Maximum length of the segments used in the queue. This is a somewhat arbitrary limit: + /// larger means that as long as we don't exceed the size, we avoid allocating more segments, + /// but if we do exceed it, then the segment becomes garbage. + /// </summary> + private const int MaxSegmentLength = 1024 * 1024; + /// <summary> + /// Lock used to protect cross-segment operations, including any updates to <see cref="_tail"/> or <see cref="_head"/> + /// and any operations that need to get a consistent view of them. + /// </summary> [NonSerialized] - private volatile Segment m_tail; - - private T[] m_serializationArray; // Used for custom serialization. - - private const int SEGMENT_SIZE = 32; - - //number of snapshot takers, GetEnumerator(), ToList() and ToArray() operations take snapshot. + private object _crossSegmentLock; + /// <summary>The current tail segment.</summary> [NonSerialized] - internal volatile int m_numSnapshotTakers = 0; + private volatile Segment _tail; + /// <summary>The current head segment.</summary> + [NonSerialized] + private volatile Segment _head; + /// <summary>Field used to temporarily store the contents of the queue for serialization.</summary> + private T[] _serializationArray; /// <summary> /// Initializes a new instance of the <see cref="ConcurrentQueue{T}"/> class. /// </summary> public ConcurrentQueue() { - m_head = m_tail = new Segment(0, this); + _crossSegmentLock = new object(); + _tail = _head = new Segment(InitialSegmentLength); + } + + /// <summary>Set the data array to be serialized.</summary> + [OnSerializing] + private void OnSerializing(StreamingContext context) + { + _serializationArray = ToArray(); + } + + /// <summary>Clear the data array that was serialized.</summary> + [OnSerialized] + private void OnSerialized(StreamingContext context) + { + _serializationArray = null; + } + + /// <summary>Construct the queue from the deserialized <see cref="_serializationArray"/>.</summary> + [OnDeserialized] + private void OnDeserialized(StreamingContext context) + { + Debug.Assert(_serializationArray != null); + InitializeFromCollection(_serializationArray); + _serializationArray = null; } /// <summary> @@ -70,34 +103,39 @@ namespace System.Collections.Concurrent /// <param name="collection">A collection from which to copy elements.</param> private void InitializeFromCollection(IEnumerable<T> collection) { - Segment localTail = new Segment(0, this);//use this local variable to avoid the extra volatile read/write. this is safe because it is only called from ctor - m_head = localTail; - - int index = 0; - foreach (T element in collection) + _crossSegmentLock = new object(); + + // Determine the initial segment size. We'll use the default, + // unless the collection is known to be larger than than, in which + // case we round its length up to a power of 2, as all segments must + // be a power of 2 in length. + int length = InitialSegmentLength; + var c = collection as ICollection<T>; + if (c != null) { - Debug.Assert(index >= 0 && index < SEGMENT_SIZE); - localTail.UnsafeAdd(element); - index++; - - if (index >= SEGMENT_SIZE) + int count = c.Count; + if (count > length) { - localTail = localTail.UnsafeGrow(); - index = 0; + length = RoundUpToPowerOf2(count); } } - m_tail = localTail; + // Initialize the segment and add all of the data to it. + _tail = _head = new Segment(length); + foreach (T item in collection) + { + Enqueue(item); + } } /// <summary> - /// Initializes a new instance of the <see cref="ConcurrentQueue{T}"/> - /// class that contains elements copied from the specified collection + /// Initializes a new instance of the <see cref="ConcurrentQueue{T}"/> class that contains elements copied + /// from the specified collection. /// </summary> - /// <param name="collection">The collection whose elements are copied to the new <see - /// cref="ConcurrentQueue{T}"/>.</param> - /// <exception cref="T:System.ArgumentNullException">The <paramref name="collection"/> argument is - /// null.</exception> + /// <param name="collection"> + /// The collection whose elements are copied to the new <see cref="ConcurrentQueue{T}"/>. + /// </param> + /// <exception cref="System.ArgumentNullException">The <paramref name="collection"/> argument is null.</exception> public ConcurrentQueue(IEnumerable<T> collection) { if (collection == null) @@ -109,37 +147,15 @@ namespace System.Collections.Concurrent } /// <summary> - /// Get the data array to be serialized - /// </summary> - [OnSerializing] - private void OnSerializing(StreamingContext context) - { - // save the data into the serialization array to be saved - m_serializationArray = ToArray(); - } - - /// <summary> - /// Construct the queue from a previously seiralized one - /// </summary> - [OnDeserialized] - private void OnDeserialized(StreamingContext context) - { - Debug.Assert(m_serializationArray != null); - InitializeFromCollection(m_serializationArray); - m_serializationArray = null; - } - - /// <summary> - /// Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an <see - /// cref="T:System.Array"/>, starting at a particular - /// <see cref="T:System.Array"/> index. + /// Copies the elements of the <see cref="ICollection"/> to an <see + /// cref="Array"/>, starting at a particular <see cref="Array"/> index. /// </summary> - /// <param name="array">The one-dimensional <see cref="T:System.Array">Array</see> that is the - /// destination of the elements copied from the - /// <see cref="T:System.Collections.Concurrent.ConcurrentBag"/>. The <see - /// cref="T:System.Array">Array</see> must have zero-based indexing.</param> - /// <param name="index">The zero-based index in <paramref name="array"/> at which copying - /// begins.</param> + /// <param name="array"> + /// The one-dimensional <see cref="Array">Array</see> that is the destination of the + /// elements copied from the <see cref="ConcurrentQueue{T}"/>. <paramref name="array"/> must have + /// zero-based indexing. + /// </param> + /// <param name="index">The zero-based index in <paramref name="array"/> at which copying begins.</param> /// <exception cref="ArgumentNullException"><paramref name="array"/> is a null reference (Nothing in /// Visual Basic).</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than @@ -148,100 +164,52 @@ namespace System.Collections.Concurrent /// <paramref name="array"/> is multidimensional. -or- /// <paramref name="array"/> does not have zero-based indexing. -or- /// <paramref name="index"/> is equal to or greater than the length of the <paramref name="array"/> - /// -or- The number of elements in the source <see cref="T:System.Collections.ICollection"/> is + /// -or- The number of elements in the source <see cref="ICollection"/> is /// greater than the available space from <paramref name="index"/> to the end of the destination /// <paramref name="array"/>. -or- The type of the source <see - /// cref="T:System.Collections.ICollection"/> cannot be cast automatically to the type of the + /// cref="ICollection"/> cannot be cast automatically to the type of the /// destination <paramref name="array"/>. /// </exception> void ICollection.CopyTo(Array array, int index) { + // Special-case when the Array is actually a T[], taking a faster path + T[] szArray = array as T[]; + if (szArray != null) + { + CopyTo(szArray, index); + return; + } + // Validate arguments. if (array == null) { throw new ArgumentNullException(nameof(array)); } - // We must be careful not to corrupt the array, so we will first accumulate an - // internal list of elements that we will then copy to the array. This requires - // some extra allocation, but is necessary since we don't know up front whether - // the array is sufficiently large to hold the stack's contents. - ((ICollection)ToList()).CopyTo(array, index); + // Otherwise, fall back to the slower path that first copies the contents + // to an array, and then uses that array's non-generic CopyTo to do the copy. + ToArray().CopyTo(array, index); } /// <summary> - /// Gets a value indicating whether access to the <see cref="T:System.Collections.ICollection"/> is + /// Gets a value indicating whether access to the <see cref="ICollection"/> is /// synchronized with the SyncRoot. /// </summary> - /// <value>true if access to the <see cref="T:System.Collections.ICollection"/> is synchronized + /// <value>true if access to the <see cref="ICollection"/> is synchronized /// with the SyncRoot; otherwise, false. For <see cref="ConcurrentQueue{T}"/>, this property always /// returns false.</value> - bool ICollection.IsSynchronized - { - // Gets a value indicating whether access to this collection is synchronized. Always returns - // false. The reason is subtle. While access is in face thread safe, it's not the case that - // locking on the SyncRoot would have prevented concurrent pushes and pops, as this property - // would typically indicate; that's because we internally use CAS operations vs. true locks. - get { return false; } - } - + bool ICollection.IsSynchronized => false; // always false, as true implies synchronization via SyncRoot /// <summary> /// Gets an object that can be used to synchronize access to the <see - /// cref="T:System.Collections.ICollection"/>. This property is not supported. - /// </summary> - /// <exception cref="T:System.NotSupportedException">The SyncRoot property is not supported.</exception> - object ICollection.SyncRoot - { - get - { - throw new NotSupportedException(Environment.GetResourceString("ConcurrentCollection_SyncRoot_NotSupported")); - } - } - - /// <summary> - /// Returns an enumerator that iterates through a collection. - /// </summary> - /// <returns>An <see cref="T:System.Collections.IEnumerator"/> that can be used to iterate through the collection.</returns> - IEnumerator IEnumerable.GetEnumerator() - { - return ((IEnumerable<T>)this).GetEnumerator(); - } - - /// <summary> - /// Attempts to add an object to the <see - /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>. + /// cref="ICollection"/>. This property is not supported. /// </summary> - /// <param name="item">The object to add to the <see - /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>. The value can be a null - /// reference (Nothing in Visual Basic) for reference types. - /// </param> - /// <returns>true if the object was added successfully; otherwise, false.</returns> - /// <remarks>For <see cref="ConcurrentQueue{T}"/>, this operation will always add the object to the - /// end of the <see cref="ConcurrentQueue{T}"/> - /// and return true.</remarks> - bool IProducerConsumerCollection<T>.TryAdd(T item) - { - Enqueue(item); - return true; - } + /// <exception cref="NotSupportedException">The SyncRoot property is not supported.</exception> + object ICollection.SyncRoot { get { throw new NotSupportedException(Environment.GetResourceString("ConcurrentCollection_SyncRoot_NotSupported")); } } - /// <summary> - /// Attempts to remove and return an object from the <see - /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>. - /// </summary> - /// <param name="item"> - /// When this method returns, if the operation was successful, <paramref name="item"/> contains the - /// object removed. If no object was available to be removed, the value is unspecified. - /// </param> - /// <returns>true if an element was removed and returned succesfully; otherwise, false.</returns> - /// <remarks>For <see cref="ConcurrentQueue{T}"/>, this operation will attempt to remove the object - /// from the beginning of the <see cref="ConcurrentQueue{T}"/>. - /// </remarks> - bool IProducerConsumerCollection<T>.TryTake(out T item) - { - return TryDequeue(out item); - } + /// <summary>Returns an enumerator that iterates through a collection.</summary> + /// <returns>An <see cref="IEnumerator"/> that can be used to iterate through the collection.</returns> + IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<T>)this).GetEnumerator(); /// <summary> /// Gets a value that indicates whether the <see cref="ConcurrentQueue{T}"/> is empty. @@ -258,126 +226,43 @@ namespace System.Collections.Concurrent { get { - Segment head = m_head; - if (!head.IsEmpty) - //fast route 1: - //if current head is not empty, then queue is not empty - return false; - else if (head.Next == null) - //fast route 2: - //if current head is empty and it's the last segment - //then queue is empty - return true; - else - //slow route: - //current head is empty and it is NOT the last segment, - //it means another thread is growing new segment - { - SpinWait spin = new SpinWait(); - while (head.IsEmpty) - { - if (head.Next == null) - return true; - - spin.SpinOnce(); - head = m_head; - } - return false; - } + // IsEmpty == !TryPeek. We use a "resultUsed:false" peek in order to avoid marking + // segments as preserved for observation, making IsEmpty a cheaper way than either + // TryPeek(out T) or Count == 0 to check whether any elements are in the queue. + T ignoredResult; + return !TryPeek(out ignoredResult, resultUsed: false); } } - /// <summary> - /// Copies the elements stored in the <see cref="ConcurrentQueue{T}"/> to a new array. - /// </summary> - /// <returns>A new array containing a snapshot of elements copied from the <see - /// cref="ConcurrentQueue{T}"/>.</returns> + /// <summary>Copies the elements stored in the <see cref="ConcurrentQueue{T}"/> to a new array.</summary> + /// <returns>A new array containing a snapshot of elements copied from the <see cref="ConcurrentQueue{T}"/>.</returns> public T[] ToArray() { - return ToList().ToArray(); - } + // Snap the current contents for enumeration. + Segment head, tail; + int headHead, tailTail; + SnapForObservation(out head, out headHead, out tail, out tailTail); - /// <summary> - /// Copies the <see cref="ConcurrentQueue{T}"/> elements to a new <see - /// cref="T:System.Collections.Generic.List{T}"/>. - /// </summary> - /// <returns>A new <see cref="T:System.Collections.Generic.List{T}"/> containing a snapshot of - /// elements copied from the <see cref="ConcurrentQueue{T}"/>.</returns> - private List<T> ToList() - { - // Increments the number of active snapshot takers. This increment must happen before the snapshot is - // taken. At the same time, Decrement must happen after list copying is over. Only in this way, can it - // eliminate race condition when Segment.TryRemove() checks whether m_numSnapshotTakers == 0. - Interlocked.Increment(ref m_numSnapshotTakers); + // Count the number of items in that snapped set, and use it to allocate an + // array of the right size. + long count = GetCount(head, headHead, tail, tailTail); + T[] arr = new T[count]; - List<T> list = new List<T>(); - try + // Now enumerate the contents, copying each element into the array. + using (IEnumerator<T> e = Enumerate(head, headHead, tail, tailTail)) { - //store head and tail positions in buffer, - Segment head, tail; - int headLow, tailHigh; - GetHeadTailPositions(out head, out tail, out headLow, out tailHigh); - - if (head == tail) - { - head.AddToList(list, headLow, tailHigh); - } - else + int i = 0; + while (e.MoveNext()) { - head.AddToList(list, headLow, SEGMENT_SIZE - 1); - Segment curr = head.Next; - while (curr != tail) - { - curr.AddToList(list, 0, SEGMENT_SIZE - 1); - curr = curr.Next; - } - //Add tail segment - tail.AddToList(list, 0, tailHigh); + arr[i++] = e.Current; } + Debug.Assert(count == i); } - finally - { - // This Decrement must happen after copying is over. - Interlocked.Decrement(ref m_numSnapshotTakers); - } - return list; - } - /// <summary> - /// Store the position of the current head and tail positions. - /// </summary> - /// <param name="head">return the head segment</param> - /// <param name="tail">return the tail segment</param> - /// <param name="headLow">return the head offset, value range [0, SEGMENT_SIZE]</param> - /// <param name="tailHigh">return the tail offset, value range [-1, SEGMENT_SIZE-1]</param> - private void GetHeadTailPositions(out Segment head, out Segment tail, - out int headLow, out int tailHigh) - { - head = m_head; - tail = m_tail; - headLow = head.Low; - tailHigh = tail.High; - SpinWait spin = new SpinWait(); - - //we loop until the observed values are stable and sensible. - //This ensures that any update order by other methods can be tolerated. - while ( - //if head and tail changed, retry - head != m_head || tail != m_tail - //if low and high pointers, retry - || headLow != head.Low || tailHigh != tail.High - //if head jumps ahead of tail because of concurrent grow and dequeue, retry - || head.m_index > tail.m_index) - { - spin.SpinOnce(); - head = m_head; - tail = m_tail; - headLow = head.Low; - tailHigh = tail.High; - } + // And return it. + return arr; } - /// <summary> /// Gets the number of elements contained in the <see cref="ConcurrentQueue{T}"/>. /// </summary> @@ -391,38 +276,140 @@ namespace System.Collections.Concurrent { get { - //store head and tail positions in buffer, Segment head, tail; - int headLow, tailHigh; - GetHeadTailPositions(out head, out tail, out headLow, out tailHigh); - - if (head == tail) + int headHead, headTail, tailHead, tailTail; + var spinner = new SpinWait(); + while (true) { - return tailHigh - headLow + 1; + // Capture the head and tail, as well as the head's head and tail. + head = _head; + tail = _tail; + headHead = Volatile.Read(ref head._headAndTail.Head); + headTail = Volatile.Read(ref head._headAndTail.Tail); + + if (head == tail) + { + // There was a single segment in the queue. If the captured + // values still (or again) represent reality, return the segment's + // count. A single segment should be the most common case once the + // queue's size has stabilized after segments have grown to + // the point where growing is no longer needed. + if (head == _head && + head == _tail && + headHead == Volatile.Read(ref head._headAndTail.Head) && + headTail == Volatile.Read(ref head._headAndTail.Tail)) + { + return GetCount(head, headHead, headTail); + } + } + else if (head._nextSegment == tail) + { + // There were two segments in the queue. Get the positions + // from the tail, and if the captured values still (or again) match + // reality, return the sum of the counts from both segments. + tailHead = Volatile.Read(ref tail._headAndTail.Head); + tailTail = Volatile.Read(ref tail._headAndTail.Tail); + if (head == _head && + tail == _tail && + headHead == Volatile.Read(ref head._headAndTail.Head) && + headTail == Volatile.Read(ref head._headAndTail.Tail) && + tailHead == Volatile.Read(ref tail._headAndTail.Head) && + tailTail == Volatile.Read(ref tail._headAndTail.Tail)) + { + // We got stable values, so we can just compute the sizes based on those + // values and return the sum of the counts of the segments. + return GetCount(head, headHead, headTail) + GetCount(tail, tailHead, tailTail); + } + } + else + { + // There were more than two segments. Take the slower path, where we freeze the + // queue and then count the now stable segments. + SnapForObservation(out head, out headHead, out tail, out tailTail); + return unchecked((int)GetCount(head, headHead, tail, tailTail)); + } + + // We raced with enqueues/dequeues and captured an inconsistent picture of the queue. + // Spin and try again. + spinner.SpinOnce(); } + } + } - //head segment - int count = SEGMENT_SIZE - headLow; + /// <summary>Computes the number of items in a segment based on a fixed head and tail in that segment.</summary> + private static int GetCount(Segment s, int head, int tail) + { + if (head != tail && head != tail - s.FreezeOffset) + { + head &= s._slotsMask; + tail &= s._slotsMask; + return head < tail ? tail - head : s._slots.Length - head + tail; + } + return 0; + } - //middle segment(s), if any, are full. - //We don't deal with overflow to be consistent with the behavior of generic types in CLR. - count += SEGMENT_SIZE * ((int)(tail.m_index - head.m_index - 1)); + /// <summary>Gets the number of items in snapped region.</summary> + private static long GetCount(Segment head, int headHead, Segment tail, int tailTail) + { + // All of the segments should have been both frozen for enqueues and preserved for observation. + // Validate that here for head and tail; we'll validate it for intermediate segments later. + Debug.Assert(head._preservedForObservation); + Debug.Assert(head._frozenForEnqueues); + Debug.Assert(tail._preservedForObservation); + Debug.Assert(tail._frozenForEnqueues); + + long count = 0; + + // Head segment. We've already marked it as frozen for enqueues, so its tail position is fixed, + // and we've already marked it as preserved for observation (before we grabbed the head), so we + // can safely enumerate from its head to its tail and access its elements. + int headTail = (head == tail ? tailTail : Volatile.Read(ref head._headAndTail.Tail)) - head.FreezeOffset; + if (headHead < headTail) + { + // Mask the head and tail for the head segment + headHead &= head._slotsMask; + headTail &= head._slotsMask; + + // Increase the count by either the one or two regions, based on whether tail + // has wrapped to be less than head. + count += headHead < headTail ? + headTail - headHead : + head._slots.Length - headHead + headTail; + } - //tail segment - count += tailHigh + 1; + // We've enumerated the head. If the tail is different from the head, we need to + // enumerate the remaining segments. + if (head != tail) + { + // Count the contents of each segment between head and tail, not including head and tail. + // Since there were segments before these, for our purposes we consider them to start at + // the 0th element, and since there is at least one segment after each, each was frozen + // by the time we snapped it, so we can iterate until each's frozen tail. + for (Segment s = head._nextSegment; s != tail; s = s._nextSegment) + { + Debug.Assert(s._preservedForObservation); + Debug.Assert(s._frozenForEnqueues); + count += s._headAndTail.Tail - s.FreezeOffset; + } - return count; + // Finally, enumerate the tail. As with the intermediate segments, there were segments + // before this in the snapped region, so we can start counting from the beginning. Unlike + // the intermediate segments, we can't just go until the Tail, as that could still be changing; + // instead we need to go until the tail we snapped for observation. + count += tailTail - tail.FreezeOffset; } - } + // Return the computed count. + return count; + } /// <summary> /// Copies the <see cref="ConcurrentQueue{T}"/> elements to an existing one-dimensional <see - /// cref="T:System.Array">Array</see>, starting at the specified array index. + /// cref="Array">Array</see>, starting at the specified array index. /// </summary> - /// <param name="array">The one-dimensional <see cref="T:System.Array">Array</see> that is the + /// <param name="array">The one-dimensional <see cref="Array">Array</see> that is the /// destination of the elements copied from the - /// <see cref="ConcurrentQueue{T}"/>. The <see cref="T:System.Array">Array</see> must have zero-based + /// <see cref="ConcurrentQueue{T}"/>. The <see cref="Array">Array</see> must have zero-based /// indexing.</param> /// <param name="index">The zero-based index in <paramref name="array"/> at which copying /// begins.</param> @@ -442,19 +429,36 @@ namespace System.Collections.Concurrent { throw new ArgumentNullException(nameof(array)); } + if (index < 0) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } - // We must be careful not to corrupt the array, so we will first accumulate an - // internal list of elements that we will then copy to the array. This requires - // some extra allocation, but is necessary since we don't know up front whether - // the array is sufficiently large to hold the stack's contents. - ToList().CopyTo(array, index); - } + // Snap for enumeration + Segment head, tail; + int headHead, tailTail; + SnapForObservation(out head, out headHead, out tail, out tailTail); + // Get the number of items to be enumerated + long count = GetCount(head, headHead, tail, tailTail); + if (index > array.Length - count) + { + throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall")); + } - /// <summary> - /// Returns an enumerator that iterates through the <see - /// cref="ConcurrentQueue{T}"/>. - /// </summary> + // Copy the items to the target array + int i = index; + using (IEnumerator<T> e = Enumerate(head, headHead, tail, tailTail)) + { + while (e.MoveNext()) + { + array[i++] = e.Current; + } + } + Debug.Assert(count == i - index); + } + + /// <summary>Returns an enumerator that iterates through the <see cref="ConcurrentQueue{T}"/>.</summary> /// <returns>An enumerator for the contents of the <see /// cref="ConcurrentQueue{T}"/>.</returns> /// <remarks> @@ -465,124 +469,195 @@ namespace System.Collections.Concurrent /// </remarks> public IEnumerator<T> GetEnumerator() { - // Increments the number of active snapshot takers. This increment must happen before the snapshot is - // taken. At the same time, Decrement must happen after the enumeration is over. Only in this way, can it - // eliminate race condition when Segment.TryRemove() checks whether m_numSnapshotTakers == 0. - Interlocked.Increment(ref m_numSnapshotTakers); - - // Takes a snapshot of the queue. - // A design flaw here: if a Thread.Abort() happens, we cannot decrement m_numSnapshotTakers. But we cannot - // wrap the following with a try/finally block, otherwise the decrement will happen before the yield return - // statements in the GetEnumerator (head, tail, headLow, tailHigh) method. Segment head, tail; - int headLow, tailHigh; - GetHeadTailPositions(out head, out tail, out headLow, out tailHigh); - - //If we put yield-return here, the iterator will be lazily evaluated. As a result a snapshot of - // the queue is not taken when GetEnumerator is initialized but when MoveNext() is first called. - // This is inconsistent with existing generic collections. In order to prevent it, we capture the - // value of m_head in a buffer and call out to a helper method. - //The old way of doing this was to return the ToList().GetEnumerator(), but ToList() was an - // unnecessary perfomance hit. - return GetEnumerator(head, tail, headLow, tailHigh); + int headHead, tailTail; + SnapForObservation(out head, out headHead, out tail, out tailTail); + return Enumerate(head, headHead, tail, tailTail); } /// <summary> - /// Helper method of GetEnumerator to seperate out yield return statement, and prevent lazy evaluation. + /// Gets the head and tail information of the current contents of the queue. + /// After this call returns, the specified region can be enumerated any number + /// of times and will not change. /// </summary> - private IEnumerator<T> GetEnumerator(Segment head, Segment tail, int headLow, int tailHigh) + private void SnapForObservation(out Segment head, out int headHead, out Segment tail, out int tailTail) { - try + lock (_crossSegmentLock) // _head and _tail may only change while the lock is held. { - SpinWait spin = new SpinWait(); + // Snap the head and tail + head = _head; + tail = _tail; + Debug.Assert(head != null); + Debug.Assert(tail != null); + Debug.Assert(tail._nextSegment == null); + + // Mark them and all segments in between as preserving, and ensure no additional items + // can be added to the tail. + for (Segment s = head; ; s = s._nextSegment) + { + s._preservedForObservation = true; + if (s == tail) break; + Debug.Assert(s._frozenForEnqueues); // any non-tail should already be marked + } + tail.EnsureFrozenForEnqueues(); // we want to prevent the tailTail from moving - if (head == tail) + // At this point, any dequeues from any segment won't overwrite the value, and + // none of the existing segments can have new items enqueued. + + headHead = Volatile.Read(ref head._headAndTail.Head); + tailTail = Volatile.Read(ref tail._headAndTail.Tail); + } + } + + /// <summary>Gets the item stored in the <paramref name="i"/>th entry in <paramref name="segment"/>.</summary> + private T GetItemWhenAvailable(Segment segment, int i) + { + Debug.Assert(segment._preservedForObservation); + + // Get the expected value for the sequence number + int expectedSequenceNumberAndMask = (i + 1) & segment._slotsMask; + + // If the expected sequence number is not yet written, we're still waiting for + // an enqueuer to finish storing it. Spin until it's there. + if ((segment._slots[i].SequenceNumber & segment._slotsMask) != expectedSequenceNumberAndMask) + { + var spinner = new SpinWait(); + while ((Volatile.Read(ref segment._slots[i].SequenceNumber) & segment._slotsMask) != expectedSequenceNumberAndMask) { - for (int i = headLow; i <= tailHigh; i++) - { - // If the position is reserved by an Enqueue operation, but the value is not written into, - // spin until the value is available. - spin.Reset(); - while (!head.m_state[i].m_value) - { - spin.SpinOnce(); - } - yield return head.m_array[i]; - } + spinner.SpinOnce(); + } + } + + // Return the value from the slot. + return segment._slots[i].Item; + } + + private IEnumerator<T> Enumerate(Segment head, int headHead, Segment tail, int tailTail) + { + Debug.Assert(head._preservedForObservation); + Debug.Assert(head._frozenForEnqueues); + Debug.Assert(tail._preservedForObservation); + Debug.Assert(tail._frozenForEnqueues); + + // Head segment. We've already marked it as not accepting any more enqueues, + // so its tail position is fixed, and we've already marked it as preserved for + // enumeration (before we grabbed its head), so we can safely enumerate from + // its head to its tail. + int headTail = (head == tail ? tailTail : Volatile.Read(ref head._headAndTail.Tail)) - head.FreezeOffset; + if (headHead < headTail) + { + headHead &= head._slotsMask; + headTail &= head._slotsMask; + + if (headHead < headTail) + { + for (int i = headHead; i < headTail; i++) yield return GetItemWhenAvailable(head, i); } else { - //iterate on head segment - for (int i = headLow; i < SEGMENT_SIZE; i++) - { - // If the position is reserved by an Enqueue operation, but the value is not written into, - // spin until the value is available. - spin.Reset(); - while (!head.m_state[i].m_value) - { - spin.SpinOnce(); - } - yield return head.m_array[i]; - } - //iterate on middle segments - Segment curr = head.Next; - while (curr != tail) - { - for (int i = 0; i < SEGMENT_SIZE; i++) - { - // If the position is reserved by an Enqueue operation, but the value is not written into, - // spin until the value is available. - spin.Reset(); - while (!curr.m_state[i].m_value) - { - spin.SpinOnce(); - } - yield return curr.m_array[i]; - } - curr = curr.Next; - } + for (int i = headHead; i < head._slots.Length; i++) yield return GetItemWhenAvailable(head, i); + for (int i = 0; i < headTail; i++) yield return GetItemWhenAvailable(head, i); + } + } - //iterate on tail segment - for (int i = 0; i <= tailHigh; i++) + // We've enumerated the head. If the tail is the same, we're done. + if (head != tail) + { + // Each segment between head and tail, not including head and tail. Since there were + // segments before these, for our purposes we consider it to start at the 0th element. + for (Segment s = head._nextSegment; s != tail; s = s._nextSegment) + { + Debug.Assert(s._preservedForObservation, "Would have had to been preserved as a segment part of enumeration"); + Debug.Assert(s._frozenForEnqueues, "Would have had to be frozen for enqueues as it's intermediate"); + + int sTail = s._headAndTail.Tail - s.FreezeOffset; + for (int i = 0; i < sTail; i++) { - // If the position is reserved by an Enqueue operation, but the value is not written into, - // spin until the value is available. - spin.Reset(); - while (!tail.m_state[i].m_value) - { - spin.SpinOnce(); - } - yield return tail.m_array[i]; + yield return GetItemWhenAvailable(s, i); } } - } - finally - { - // This Decrement must happen after the enumeration is over. - Interlocked.Decrement(ref m_numSnapshotTakers); + + // Enumerate the tail. Since there were segments before this, we can just start at + // its beginning, and iterate until the tail we already grabbed. + tailTail -= tail.FreezeOffset; + for (int i = 0; i < tailTail; i++) + { + yield return GetItemWhenAvailable(tail, i); + } } } - /// <summary> - /// Adds an object to the end of the <see cref="ConcurrentQueue{T}"/>. - /// </summary> - /// <param name="item">The object to add to the end of the <see - /// cref="ConcurrentQueue{T}"/>. The value can be a null reference - /// (Nothing in Visual Basic) for reference types. + /// <summary>Round the specified value up to the next power of 2, if it isn't one already.</summary> + private static int RoundUpToPowerOf2(int i) + { + --i; + i |= i >> 1; + i |= i >> 2; + i |= i >> 4; + i |= i >> 8; + i |= i >> 16; + return i + 1; + } + + /// <summary>Adds an object to the end of the <see cref="ConcurrentQueue{T}"/>.</summary> + /// <param name="item"> + /// The object to add to the end of the <see cref="ConcurrentQueue{T}"/>. + /// The value can be a null reference (Nothing in Visual Basic) for reference types. /// </param> public void Enqueue(T item) { - SpinWait spin = new SpinWait(); + // Try to enqueue to the current tail. + if (!_tail.TryEnqueue(item)) + { + // If we're unable to, we need to take a slow path that will + // try to add a new tail segment. + EnqueueSlow(item); + } + } + + /// <summary>Adds to the end of the queue, adding a new segment if necessary.</summary> + private void EnqueueSlow(T item) + { while (true) { - Segment tail = m_tail; - if (tail.TryAppend(item)) + Segment tail = _tail; + + // Try to append to the existing tail. + if (tail.TryEnqueue(item)) + { return; - spin.SpinOnce(); + } + + // If we were unsuccessful, take the lock so that we can compare and manipulate + // the tail. Assuming another enqueuer hasn't already added a new segment, + // do so, then loop around to try enqueueing again. + lock (_crossSegmentLock) + { + if (tail == _tail) + { + // Make sure no one else can enqueue to this segment. + tail.EnsureFrozenForEnqueues(); + + // We determine the new segment's length based on the old length. + // In general, we double the size of the segment, to make it less likely + // that we'll need to grow again. However, if the tail segment is marked + // as preserved for observation, something caused us to avoid reusing this + // segment, and if that happens a lot and we grow, we'll end up allocating + // lots of wasted space. As such, in such situations we reset back to the + // initial segment length; if these observations are happening frequently, + // this will help to avoid wasted memory, and if they're not, we'll + // relatively quickly grow again to a larger size. + int nextSize = tail._preservedForObservation ? InitialSegmentLength : tail.Capacity * 2; + var newTail = new Segment(nextSize); + + // Hook up the new tail. + tail._nextSegment = newTail; + _tail = newTail; + } + } } } - /// <summary> /// Attempts to remove and return the object at the beginning of the <see /// cref="ConcurrentQueue{T}"/>. @@ -591,369 +666,456 @@ namespace System.Collections.Concurrent /// When this method returns, if the operation was successful, <paramref name="result"/> contains the /// object removed. If no object was available to be removed, the value is unspecified. /// </param> - /// <returns>true if an element was removed and returned from the beggining of the <see - /// cref="ConcurrentQueue{T}"/> - /// succesfully; otherwise, false.</returns> - public bool TryDequeue(out T result) + /// <returns> + /// true if an element was removed and returned from the beginning of the + /// <see cref="ConcurrentQueue{T}"/> successfully; otherwise, false. + /// </returns> + public bool TryDequeue(out T result) => + _head.TryDequeue(out result) || // fast-path that operates just on the head segment + TryDequeueSlow(out result); // slow path that needs to fix up segments + + /// <summary>Tries to dequeue an item, removing empty segments as needed.</summary> + private bool TryDequeueSlow(out T item) { - while (!IsEmpty) + while (true) { - Segment head = m_head; - if (head.TryRemove(out result)) + // Get the current head + Segment head = _head; + + // Try to take. If we're successful, we're done. + if (head.TryDequeue(out item)) + { + return true; + } + + // Check to see whether this segment is the last. If it is, we can consider + // this to be a moment-in-time empty condition (even though between the TryDequeue + // check and this check, another item could have arrived). + if (head._nextSegment == null) + { + item = default(T); + return false; + } + + // At this point we know that head.Next != null, which means + // this segment has been frozen for additional enqueues. But between + // the time that we ran TryDequeue and checked for a next segment, + // another item could have been added. Try to dequeue one more time + // to confirm that the segment is indeed empty. + Debug.Assert(head._frozenForEnqueues); + if (head.TryDequeue(out item)) + { return true; - //since method IsEmpty spins, we don't need to spin in the while loop + } + + // This segment is frozen (nothing more can be added) and empty (nothing is in it). + // Update head to point to the next segment in the list, assuming no one's beat us to it. + lock (_crossSegmentLock) + { + if (head == _head) + { + _head = head._nextSegment; + } + } } - result = default(T); - return false; } /// <summary> /// Attempts to return an object from the beginning of the <see cref="ConcurrentQueue{T}"/> /// without removing it. /// </summary> - /// <param name="result">When this method returns, <paramref name="result"/> contains an object from - /// the beginning of the <see cref="T:System.Collections.Concurrent.ConccurrentQueue{T}"/> or an - /// unspecified value if the operation failed.</param> + /// <param name="result"> + /// When this method returns, <paramref name="result"/> contains an object from + /// the beginning of the <see cref="Concurrent.ConcurrentQueue{T}"/> or default(T) + /// if the operation failed. + /// </param> /// <returns>true if and object was returned successfully; otherwise, false.</returns> - public bool TryPeek(out T result) - { - Interlocked.Increment(ref m_numSnapshotTakers); + /// <remarks> + /// For determining whether the collection contains any items, use of the <see cref="IsEmpty"/> + /// property is recommended rather than peeking. + /// </remarks> + public bool TryPeek(out T result) => TryPeek(out result, resultUsed: true); - while (!IsEmpty) + /// <summary>Attempts to retrieve the value for the first element in the queue.</summary> + /// <param name="result">The value of the first element, if found.</param> + /// <param name="resultUsed">true if the result is neede; otherwise false if only the true/false outcome is needed.</param> + /// <returns>true if an element was found; otherwise, false.</returns> + private bool TryPeek(out T result, bool resultUsed) + { + // Starting with the head segment, look through all of the segments + // for the first one we can find that's not empty. + Segment s = _head; + while (true) { - Segment head = m_head; - if (head.TryPeek(out result)) + // Grab the next segment from this one, before we peek. + // This is to be able to see whether the value has changed + // during the peek operation. + Segment next = Volatile.Read(ref s._nextSegment); + + // Peek at the segment. If we find an element, we're done. + if (s.TryPeek(out result, resultUsed)) { - Interlocked.Decrement(ref m_numSnapshotTakers); return true; } - //since method IsEmpty spins, we don't need to spin in the while loop + + // The current segment was empty at the moment we checked. + + if (next != null) + { + // If prior to the peek there was already a next segment, then + // during the peek no additional items could have been enqueued + // to it and we can just move on to check the next segment. + Debug.Assert(next == s._nextSegment); + s = next; + } + else if (Volatile.Read(ref s._nextSegment) == null) + { + // The next segment is null. Nothing more to peek at. + break; + } + + // The next segment was null before we peeked but non-null after. + // That means either when we peeked the first segment had + // already been frozen but the new segment not yet added, + // or that the first segment was empty and between the time + // that we peeked and then checked _nextSegment, so many items + // were enqueued that we filled the first segment and went + // into the next. Since we need to peek in order, we simply + // loop around again to peek on the same segment. The next + // time around on this segment we'll then either successfully + // peek or we'll find that next was non-null before peeking, + // and we'll traverse to that segment. } + result = default(T); - Interlocked.Decrement(ref m_numSnapshotTakers); return false; } - /// <summary> - /// private class for ConcurrentQueue. - /// a queue is a linked list of small arrays, each node is called a segment. - /// A segment contains an array, a pointer to the next segment, and m_low, m_high indices recording - /// the first and last valid elements of the array. + /// Removes all objects from the <see cref="ConcurrentQueue{T}"/>. /// </summary> - private class Segment + public void Clear() { - //we define two volatile arrays: m_array and m_state. Note that the accesses to the array items - //do not get volatile treatment. But we don't need to worry about loading adjacent elements or - //store/load on adjacent elements would suffer reordering. - // - Two stores: these are at risk, but CLRv2 memory model guarantees store-release hence we are safe. - // - Two loads: because one item from two volatile arrays are accessed, the loads of the array references - // are sufficient to prevent reordering of the loads of the elements. - internal volatile T[] m_array; - - // For each entry in m_array, the corresponding entry in m_state indicates whether this position contains - // a valid value. m_state is initially all false. - internal volatile VolatileBool[] m_state; - - //pointer to the next segment. null if the current segment is the last segment - private volatile Segment m_next; - - //We use this zero based index to track how many segments have been created for the queue, and - //to compute how many active segments are there currently. - // * The number of currently active segments is : m_tail.m_index - m_head.m_index + 1; - // * m_index is incremented with every Segment.Grow operation. We use Int64 type, and we can safely - // assume that it never overflows. To overflow, we need to do 2^63 increments, even at a rate of 4 - // billion (2^32) increments per second, it takes 2^31 seconds, which is about 64 years. - internal readonly long m_index; - - //indices of where the first and last valid values - // - m_low points to the position of the next element to pop from this segment, range [0, infinity) - // m_low >= SEGMENT_SIZE implies the segment is disposable - // - m_high points to the position of the latest pushed element, range [-1, infinity) - // m_high == -1 implies the segment is new and empty - // m_high >= SEGMENT_SIZE-1 means this segment is ready to grow. - // and the thread who sets m_high to SEGMENT_SIZE-1 is responsible to grow the segment - // - Math.Min(m_low, SEGMENT_SIZE) > Math.Min(m_high, SEGMENT_SIZE-1) implies segment is empty - // - initially m_low =0 and m_high=-1; - private volatile int m_low; - private volatile int m_high; - - private volatile ConcurrentQueue<T> m_source; - - /// <summary> - /// Create and initialize a segment with the specified index. - /// </summary> - internal Segment(long index, ConcurrentQueue<T> source) + lock (_crossSegmentLock) { - m_array = new T[SEGMENT_SIZE]; - m_state = new VolatileBool[SEGMENT_SIZE]; //all initialized to false - m_high = -1; - Debug.Assert(index >= 0); - m_index = index; - m_source = source; - } - - /// <summary> - /// return the next segment - /// </summary> - internal Segment Next - { - get { return m_next; } - } - - - /// <summary> - /// return true if the current segment is empty (doesn't have any element available to dequeue, - /// false otherwise - /// </summary> - internal bool IsEmpty - { - get { return (Low > High); } - } - - /// <summary> - /// Add an element to the tail of the current segment - /// exclusively called by ConcurrentQueue.InitializedFromCollection - /// InitializeFromCollection is responsible to guaratee that there is no index overflow, - /// and there is no contention - /// </summary> - /// <param name="value"></param> - internal void UnsafeAdd(T value) - { - Debug.Assert(m_high < SEGMENT_SIZE - 1); - m_high++; - m_array[m_high] = value; - m_state[m_high].m_value = true; + // Simply substitute a new segment for the existing head/tail, + // as is done in the constructor. Operations currently in flight + // may still read from or write to an existing segment that's + // getting dropped, meaning that in flight operations may not be + // linear with regards to this clear operation. To help mitigate + // in-flight operations enqueuing onto the tail that's about to + // be dropped, we first freeze it; that'll force enqueuers to take + // this lock to synchronize and see the new tail. + _tail.EnsureFrozenForEnqueues(); + _tail = _head = new Segment(InitialSegmentLength); } + } - /// <summary> - /// Create a new segment and append to the current one - /// Does not update the m_tail pointer - /// exclusively called by ConcurrentQueue.InitializedFromCollection - /// InitializeFromCollection is responsible to guaratee that there is no index overflow, - /// and there is no contention - /// </summary> - /// <returns>the reference to the new Segment</returns> - internal Segment UnsafeGrow() + /// <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}"/>. + /// </summary> + [DebuggerDisplay("Capacity = {Capacity}")] + private sealed class Segment + { + // Segment design is inspired by the algorithm outlined at: + // http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue + + /// <summary>The array of items in this queue. Each slot contains the item in that slot and its "sequence number".</summary> + internal readonly Slot[] _slots; + /// <summary>Mask for quickly accessing a position within the queue's array.</summary> + internal readonly int _slotsMask; + /// <summary>The head and tail positions, with padding to help avoid false sharing contention.</summary> + /// <remarks>Dequeueing happens from the head, enqueueing happens at the tail.</remarks> + internal PaddedHeadAndTail _headAndTail; // mutable struct: do not make this readonly + + /// <summary>Indicates whether the segment has been marked such that dequeues don't overwrite the removed data.</summary> + internal bool _preservedForObservation; + /// <summary>Indicates whether the segment has been marked such that no additional items may be enqueued.</summary> + internal bool _frozenForEnqueues; + /// <summary>The segment following this one in the queue, or null if this segment is the last in the queue.</summary> + internal Segment _nextSegment; + + /// <summary>Creates the segment.</summary> + /// <param name="boundedLength"> + /// The maximum number of elements the segment can contain. Must be a power of 2. + /// </param> + public Segment(int boundedLength) { - Debug.Assert(m_high >= SEGMENT_SIZE - 1); - Segment newSegment = new Segment(m_index + 1, m_source); //m_index is Int64, we don't need to worry about overflow - m_next = newSegment; - return newSegment; + // Validate the length + Debug.Assert(boundedLength >= 2, $"Must be >= 2, got {boundedLength}"); + Debug.Assert((boundedLength & (boundedLength - 1)) == 0, $"Must be a power of 2, got {boundedLength}"); + + // Initialize the slots and the mask. The mask is used as a way of quickly doing "% _slots.Length", + // instead letting us do "& _slotsMask". + _slots = new Slot[boundedLength]; + _slotsMask = boundedLength - 1; + + // Initialize the sequence number for each slot. The sequence number provides a ticket that + // allows dequeuers to know whether they can dequeue and enqueuers to know whether they can + // enqueue. An enqueuer at position N can enqueue when the sequence number is N, and a dequeuer + // for position N can dequeue when the sequence number is N + 1. When an enqueuer is done writing + // at position N, it sets the sequence number to N so that a dequeuer will be able to dequeue, + // and when a dequeuer is done dequeueing at position N, it sets the sequence number to N + _slots.Length, + // so that when an enqueuer loops around the slots, it'll find that the sequence number at + // position N is N. This also means that when an enqueuer finds that at position N the sequence + // number is < N, there is still a value in that slot, i.e. the segment is full, and when a + // dequeuer finds that the value in a slot is < N + 1, there is nothing currently available to + // dequeue. (It is possible for multiple enqueuers to enqueue concurrently, writing into + // subsequent slots, and to have the first enqueuer take longer, so that the slots for 1, 2, 3, etc. + // may have values, but the 0th slot may still be being filled... in that case, TryDequeue will + // return false.) + for (int i = 0; i < _slots.Length; i++) + { + _slots[i].SequenceNumber = i; + } } - /// <summary> - /// Create a new segment and append to the current one - /// Update the m_tail pointer - /// This method is called when there is no contention - /// </summary> - internal void Grow() - { - //no CAS is needed, since there is no contention (other threads are blocked, busy waiting) - Segment newSegment = new Segment(m_index + 1, m_source); //m_index is Int64, we don't need to worry about overflow - m_next = newSegment; - Debug.Assert(m_source.m_tail == this); - m_source.m_tail = m_next; - } + /// <summary>Gets the number of elements this segment can store.</summary> + internal int Capacity => _slots.Length; + /// <summary>Gets the "freeze offset" for this segment.</summary> + internal int FreezeOffset => _slots.Length * 2; /// <summary> - /// Try to append an element at the end of this segment. + /// Ensures that the segment will not accept any subsequent enqueues that aren't already underway. /// </summary> - /// <param name="value">the element to append</param> - /// <param name="tail">The tail.</param> - /// <returns>true if the element is appended, false if the current segment is full</returns> - /// <remarks>if appending the specified element succeeds, and after which the segment is full, - /// then grow the segment</remarks> - internal bool TryAppend(T value) + /// <remarks> + /// When we mark a segment as being frozen for additional enqueues, + /// we set the <see cref="_frozenForEnqueues"/> bool, but that's mostly + /// as a small helper to avoid marking it twice. The real marking comes + /// by modifying the Tail for the segment, increasing it by this + /// <see cref="FreezeOffset"/>. This effectively knocks it off the + /// sequence expected by future enqueuers, such that any additional enqueuer + /// will be unable to enqueue due to it not lining up with the expected + /// sequence numbers. This value is chosen specially so that Tail will grow + /// to a value that maps to the same slot but that won't be confused with + /// any other enqueue/dequeue sequence number. + /// </remarks> + internal void EnsureFrozenForEnqueues() // must only be called while queue's segment lock is held { - //quickly check if m_high is already over the boundary, if so, bail out - if (m_high >= SEGMENT_SIZE - 1) + if (!_frozenForEnqueues) // flag used to ensure we don't increase the Tail more than once if frozen more than once { - return false; - } + _frozenForEnqueues = true; - //Now we will use a CAS to increment m_high, and store the result in newhigh. - //Depending on how many free spots left in this segment and how many threads are doing this Increment - //at this time, the returning "newhigh" can be - // 1) < SEGMENT_SIZE - 1 : we took a spot in this segment, and not the last one, just insert the value - // 2) == SEGMENT_SIZE - 1 : we took the last spot, insert the value AND grow the segment - // 3) > SEGMENT_SIZE - 1 : we failed to reserve a spot in this segment, we return false to - // Queue.Enqueue method, telling it to try again in the next segment. - - int newhigh = SEGMENT_SIZE; //initial value set to be over the boundary - - //We need do Interlocked.Increment and value/state update in a finally block to ensure that they run - //without interuption. This is to prevent anything from happening between them, and another dequeue - //thread maybe spinning forever to wait for m_state[] to be true; - try - { } - finally - { - newhigh = Interlocked.Increment(ref m_high); - if (newhigh <= SEGMENT_SIZE - 1) + // Increase the tail by FreezeOffset, spinning until we're successful in doing so. + var spinner = new SpinWait(); + while (true) { - m_array[newhigh] = value; - m_state[newhigh].m_value = true; - } - - //if this thread takes up the last slot in the segment, then this thread is responsible - //to grow a new segment. Calling Grow must be in the finally block too for reliability reason: - //if thread abort during Grow, other threads will be left busy spinning forever. - if (newhigh == SEGMENT_SIZE - 1) - { - Grow(); + int tail = Volatile.Read(ref _headAndTail.Tail); + if (Interlocked.CompareExchange(ref _headAndTail.Tail, tail + FreezeOffset, tail) == tail) + { + break; + } + spinner.SpinOnce(); } } - - //if newhigh <= SEGMENT_SIZE-1, it means the current thread successfully takes up a spot - return newhigh <= SEGMENT_SIZE - 1; } - - /// <summary> - /// try to remove an element from the head of current segment - /// </summary> - /// <param name="result">The result.</param> - /// <param name="head">The head.</param> - /// <returns>return false only if the current segment is empty</returns> - internal bool TryRemove(out T result) + /// <summary>Tries to dequeue an element from the queue.</summary> + public bool TryDequeue(out T item) { - SpinWait spin = new SpinWait(); - int lowLocal = Low, highLocal = High; - while (lowLocal <= highLocal) + // Loop in case of contention... + var spinner = new SpinWait(); + while (true) { - //try to update m_low - if (Interlocked.CompareExchange(ref m_low, lowLocal + 1, lowLocal) == lowLocal) - { - //if the specified value is not available (this spot is taken by a push operation, - // but the value is not written into yet), then spin - SpinWait spinLocal = new SpinWait(); - while (!m_state[lowLocal].m_value) - { - spinLocal.SpinOnce(); - } - result = m_array[lowLocal]; + // Get the head at which to try to dequeue. + int currentHead = Volatile.Read(ref _headAndTail.Head); + int slotsIndex = currentHead & _slotsMask; - // If there is no other thread taking snapshot (GetEnumerator(), ToList(), etc), reset the deleted entry to null. - // It is ok if after this conditional check m_numSnapshotTakers becomes > 0, because new snapshots won't include - // the deleted entry at m_array[lowLocal]. - if (m_source.m_numSnapshotTakers <= 0) - { - m_array[lowLocal] = default(T); //release the reference to the object. - } + // Read the sequence number for the head position. + int sequenceNumber = Volatile.Read(ref _slots[slotsIndex].SequenceNumber); - //if the current thread sets m_low to SEGMENT_SIZE, which means the current segment becomes - //disposable, then this thread is responsible to dispose this segment, and reset m_head - if (lowLocal + 1 >= SEGMENT_SIZE) + // We can dequeue from this slot if it's been filled by an enqueuer, which + // would have left the sequence number at pos+1. + int diff = sequenceNumber - (currentHead + 1); + if (diff == 0) + { + // We may be racing with other dequeuers. Try to reserve the slot by incrementing + // the head. Once we've done that, no one else will be able to read from this slot, + // and no enqueuer will be able to read from this slot until we've written the new + // sequence number. WARNING: The next few lines are not reliable on a runtime that + // supports thread aborts. If a thread abort were to sneak in after the CompareExchange + // but before the Volatile.Write, enqueuers trying to enqueue into this slot would + // spin indefinitely. If this implementation is ever used on such a platform, this + // if block should be wrapped in a finally / prepared region. + if (Interlocked.CompareExchange(ref _headAndTail.Head, currentHead + 1, currentHead) == currentHead) { - // Invariant: we only dispose the current m_head, not any other segment - // In usual situation, disposing a segment is simply seting m_head to m_head.m_next - // But there is one special case, where m_head and m_tail points to the same and ONLY - //segment of the queue: Another thread A is doing Enqueue and finds that it needs to grow, - //while the *current* thread is doing *this* Dequeue operation, and finds that it needs to - //dispose the current (and ONLY) segment. Then we need to wait till thread A finishes its - //Grow operation, this is the reason of having the following while loop - spinLocal = new SpinWait(); - while (m_next == null) + // Successfully reserved the slot. Note that after the above CompareExchange, other threads + // trying to dequeue from this slot will end up spinning until we do the subsequent Write. + item = _slots[slotsIndex].Item; + if (!Volatile.Read(ref _preservedForObservation)) { - spinLocal.SpinOnce(); + // If we're preserving, though, we don't zero out the slot, as we need it for + // enumerations, peeking, ToArray, etc. And we don't update the sequence number, + // so that an enqueuer will see it as full and be forced to move to a new segment. + _slots[slotsIndex].Item = default(T); + Volatile.Write(ref _slots[slotsIndex].SequenceNumber, currentHead + _slots.Length); } - Debug.Assert(m_source.m_head == this); - m_source.m_head = m_next; + return true; } - return true; } - else + else if (diff < 0) { - //CAS failed due to contention: spin briefly and retry - spin.SpinOnce(); - lowLocal = Low; highLocal = High; + // The sequence number was less than what we needed, which means this slot doesn't + // yet contain a value we can dequeue, i.e. the segment is empty. Technically it's + // possible that multiple enqueuers could have written concurrently, with those + // getting later slots actually finishing first, so there could be elements after + // this one that are available, but we need to dequeue in order. So before declaring + // failure and that the segment is empty, we check the tail to see if we're actually + // empty or if we're just waiting for items in flight or after this one to become available. + bool frozen = _frozenForEnqueues; + int currentTail = Volatile.Read(ref _headAndTail.Tail); + if (currentTail - currentHead <= 0 || (frozen && (currentTail - FreezeOffset - currentHead <= 0))) + { + item = default(T); + return false; + } + + // It's possible it could have become frozen after we checked _frozenForEnqueues + // and before reading the tail. That's ok: in that rare race condition, we just + // loop around again. } - }//end of while - result = default(T); - return false; + + // Lost a race. Spin a bit, then try again. + spinner.SpinOnce(); + } } - /// <summary> - /// try to peek the current segment - /// </summary> - /// <param name="result">holds the return value of the element at the head position, - /// value set to default(T) if there is no such an element</param> - /// <returns>true if there are elements in the current segment, false otherwise</returns> - internal bool TryPeek(out T result) + /// <summary>Tries to peek at an element from the queue, without removing it.</summary> + public bool TryPeek(out T result, bool resultUsed) { - result = default(T); - int lowLocal = Low; - if (lowLocal > High) - return false; - SpinWait spin = new SpinWait(); - while (!m_state[lowLocal].m_value) + if (resultUsed) { - spin.SpinOnce(); + // In order to ensure we don't get a torn read on the value, we mark the segment + // as preserving for observation. Additional items can still be enqueued to this + // segment, but no space will be freed during dequeues, such that the segment will + // no longer be reusable. + _preservedForObservation = true; + Interlocked.MemoryBarrier(); } - result = m_array[lowLocal]; - return true; - } - /// <summary> - /// Adds part or all of the current segment into a List. - /// </summary> - /// <param name="list">the list to which to add</param> - /// <param name="start">the start position</param> - /// <param name="end">the end position</param> - internal void AddToList(List<T> list, int start, int end) - { - for (int i = start; i <= end; i++) + // Loop in case of contention... + var spinner = new SpinWait(); + while (true) { - SpinWait spin = new SpinWait(); - while (!m_state[i].m_value) + // Get the head at which to try to peek. + int currentHead = Volatile.Read(ref _headAndTail.Head); + int slotsIndex = currentHead & _slotsMask; + + // Read the sequence number for the head position. + int sequenceNumber = Volatile.Read(ref _slots[slotsIndex].SequenceNumber); + + // We can peek from this slot if it's been filled by an enqueuer, which + // would have left the sequence number at pos+1. + int diff = sequenceNumber - (currentHead + 1); + if (diff == 0) { - spin.SpinOnce(); + result = resultUsed ? _slots[slotsIndex].Item : default(T); + return true; + } + else if (diff < 0) + { + // The sequence number was less than what we needed, which means this slot doesn't + // yet contain a value we can peek, i.e. the segment is empty. Technically it's + // possible that multiple enqueuers could have written concurrently, with those + // getting later slots actually finishing first, so there could be elements after + // this one that are available, but we need to peek in order. So before declaring + // failure and that the segment is empty, we check the tail to see if we're actually + // empty or if we're just waiting for items in flight or after this one to become available. + bool frozen = _frozenForEnqueues; + int currentTail = Volatile.Read(ref _headAndTail.Tail); + if (currentTail - currentHead <= 0 || (frozen && (currentTail - FreezeOffset - currentHead <= 0))) + { + result = default(T); + return false; + } + + // It's possible it could have become frozen after we checked _frozenForEnqueues + // and before reading the tail. That's ok: in that rare race condition, we just + // loop around again. } - list.Add(m_array[i]); + + // Lost a race. Spin a bit, then try again. + spinner.SpinOnce(); } } /// <summary> - /// return the position of the head of the current segment - /// Value range [0, SEGMENT_SIZE], if it's SEGMENT_SIZE, it means this segment is exhausted and thus empty + /// Attempts to enqueue the item. If successful, the item will be stored + /// in the queue and true will be returned; otherwise, the item won't be stored, and false + /// will be returned. /// </summary> - internal int Low + public bool TryEnqueue(T item) { - get + // Loop in case of contention... + var spinner = new SpinWait(); + while (true) { - return Math.Min(m_low, SEGMENT_SIZE); + // Get the tail at which to try to return. + int currentTail = Volatile.Read(ref _headAndTail.Tail); + int slotsIndex = currentTail & _slotsMask; + + // Read the sequence number for the tail position. + int sequenceNumber = Volatile.Read(ref _slots[slotsIndex].SequenceNumber); + + // The slot is empty and ready for us to enqueue into it if its sequence + // number matches the slot. + int diff = sequenceNumber - currentTail; + if (diff == 0) + { + // We may be racing with other enqueuers. Try to reserve the slot by incrementing + // the tail. Once we've done that, no one else will be able to write to this slot, + // and no dequeuer will be able to read from this slot until we've written the new + // sequence number. WARNING: The next few lines are not reliable on a runtime that + // supports thread aborts. If a thread abort were to sneak in after the CompareExchange + // but before the Volatile.Write, other threads will spin trying to access this slot. + // If this implementation is ever used on such a platform, this if block should be + // wrapped in a finally / prepared region. + if (Interlocked.CompareExchange(ref _headAndTail.Tail, currentTail + 1, currentTail) == currentTail) + { + // Successfully reserved the slot. Note that after the above CompareExchange, other threads + // trying to return will end up spinning until we do the subsequent Write. + _slots[slotsIndex].Item = item; + Volatile.Write(ref _slots[slotsIndex].SequenceNumber, currentTail + 1); + return true; + } + } + else if (diff < 0) + { + // The sequence number was less than what we needed, which means this slot still + // contains a value, i.e. the segment is full. Technically it's possible that multiple + // dequeuers could have read concurrently, with those getting later slots actually + // finishing first, so there could be spaces after this one that are available, but + // we need to enqueue in order. + return false; + } + + // Lost a race. Spin a bit, then try again. + spinner.SpinOnce(); } } - /// <summary> - /// return the logical position of the tail of the current segment - /// Value range [-1, SEGMENT_SIZE-1]. When it's -1, it means this is a new segment and has no elemnet yet - /// </summary> - internal int High + /// <summary>Represents a slot in the queue.</summary> + [StructLayout(LayoutKind.Auto)] + [DebuggerDisplay("Item = {Item}, SequenceNumber = {SequenceNumber}")] + internal struct Slot { - get - { - //if m_high > SEGMENT_SIZE, it means it's out of range, we should return - //SEGMENT_SIZE-1 as the logical position - return Math.Min(m_high, SEGMENT_SIZE - 1); - } + /// <summary>The item.</summary> + public T Item; + /// <summary>The sequence number for this slot, used to synchronize between enqueuers and dequeuers.</summary> + public int SequenceNumber; } - } - }//end of class Segment + } - /// <summary> - /// A wrapper struct for volatile bool, please note the copy of the struct it self will not be volatile - /// for example this statement will not include in volatilness operation volatileBool1 = volatileBool2 the jit will copy the struct and will ignore the volatile - /// </summary> - struct VolatileBool + /// <summary>Padded head and tail indices, to avoid false sharing between producers and consumers.</summary> + [DebuggerDisplay("Head = {Head}, Tail = {Tail}")] + [StructLayout(LayoutKind.Explicit, Size = 192)] // padding before/between/after fields based on typical cache line size of 64 + internal struct PaddedHeadAndTail { - public VolatileBool(bool value) - { - m_value = value; - } - public volatile bool m_value; + [FieldOffset(64)] public int Head; + [FieldOffset(128)] public int Tail; } } diff --git a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs index c36d96c26c..10a5201f6c 100644 --- a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs +++ b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs @@ -20,7 +20,6 @@ using System.Diagnostics.Contracts; using System.Runtime.ConstrainedExecution; using System.Runtime.Serialization; using System.Security; -using System.Security.Permissions; using System.Threading; namespace System.Collections.Concurrent @@ -45,7 +44,7 @@ namespace System.Collections.Concurrent /// </remarks> [DebuggerDisplay("Count = {Count}")] [DebuggerTypeProxy(typeof(SystemCollectionsConcurrent_ProducerConsumerCollectionDebugView<>))] - public class ConcurrentStack<T> : IProducerConsumerCollection<T>, IReadOnlyCollection<T> + internal class ConcurrentStack<T> : IProducerConsumerCollection<T>, IReadOnlyCollection<T> { /// <summary> /// A simple (internal) node type used to store elements of concurrent stacks and queues. @@ -79,61 +78,6 @@ namespace System.Collections.Concurrent } /// <summary> - /// Initializes a new instance of the <see cref="ConcurrentStack{T}"/> - /// class that contains elements copied from the specified collection - /// </summary> - /// <param name="collection">The collection whose elements are copied to the new <see - /// cref="ConcurrentStack{T}"/>.</param> - /// <exception cref="T:System.ArgumentNullException">The <paramref name="collection"/> argument is - /// null.</exception> - public ConcurrentStack(IEnumerable<T> collection) - { - if (collection == null) - { - throw new ArgumentNullException(nameof(collection)); - } - InitializeFromCollection(collection); - } - - /// <summary> - /// Initializes the contents of the stack from an existing collection. - /// </summary> - /// <param name="collection">A collection from which to copy elements.</param> - private void InitializeFromCollection(IEnumerable<T> collection) - { - // We just copy the contents of the collection to our stack. - Node lastNode = null; - foreach (T element in collection) - { - Node newNode = new Node(element); - newNode.m_next = lastNode; - lastNode = newNode; - } - - m_head = lastNode; - } - - /// <summary> - /// Gets a value that indicates whether the <see cref="ConcurrentStack{T}"/> is empty. - /// </summary> - /// <value>true if the <see cref="ConcurrentStack{T}"/> is empty; otherwise, false.</value> - /// <remarks> - /// For determining whether the collection contains any items, use of this property is recommended - /// rather than retrieving the number of items from the <see cref="Count"/> property and comparing it - /// to 0. However, as this collection is intended to be accessed concurrently, it may be the case - /// that another thread will modify the collection after <see cref="IsEmpty"/> returns, thus invalidating - /// the result. - /// </remarks> - public bool IsEmpty - { - // Checks whether the stack is empty. Clearly the answer may be out of date even prior to - // the function returning (i.e. if another thread concurrently adds to the stack). It does - // guarantee, however, that, if another thread does not mutate the stack, a subsequent call - // to TryPop will return true -- i.e. it will also read the stack as non-empty. - get { return m_head == null; } - } - - /// <summary> /// Gets the number of elements contained in the <see cref="ConcurrentStack{T}"/>. /// </summary> /// <value>The number of elements contained in the <see cref="ConcurrentStack{T}"/>.</value> @@ -196,18 +140,6 @@ namespace System.Collections.Concurrent } /// <summary> - /// Removes all objects from the <see cref="ConcurrentStack{T}"/>. - /// </summary> - public void Clear() - { - // Clear the list by setting the head to null. We don't need to use an atomic - // operation for this: anybody who is mutating the head by pushing or popping - // will need to use an atomic operation to guarantee they serialize and don't - // overwrite our setting of the head to null. - m_head = null; - } - - /// <summary> /// Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an <see /// cref="T:System.Array"/>, starting at a particular /// <see cref="T:System.Array"/> index. @@ -306,79 +238,6 @@ namespace System.Collections.Concurrent PushCore(newNode, newNode); } - /// <summary> - /// Inserts multiple objects at the top of the <see cref="ConcurrentStack{T}"/> atomically. - /// </summary> - /// <param name="items">The objects to push onto the <see cref="ConcurrentStack{T}"/>.</param> - /// <exception cref="ArgumentNullException"><paramref name="items"/> is a null reference - /// (Nothing in Visual Basic).</exception> - /// <remarks> - /// When adding multiple items to the stack, using PushRange is a more efficient - /// mechanism than using <see cref="Push"/> one item at a time. Additionally, PushRange - /// guarantees that all of the elements will be added atomically, meaning that no other threads will - /// be able to inject elements between the elements being pushed. Items at lower indices in - /// the <paramref name="items"/> array will be pushed before items at higher indices. - /// </remarks> - public void PushRange(T[] items) - { - if (items == null) - { - throw new ArgumentNullException(nameof(items)); - } - PushRange(items, 0, items.Length); - } - - /// <summary> - /// Inserts multiple objects at the top of the <see cref="ConcurrentStack{T}"/> atomically. - /// </summary> - /// <param name="items">The objects to push onto the <see cref="ConcurrentStack{T}"/>.</param> - /// <param name="startIndex">The zero-based offset in <paramref name="items"/> at which to begin - /// inserting elements onto the top of the <see cref="ConcurrentStack{T}"/>.</param> - /// <param name="count">The number of elements to be inserted onto the top of the <see - /// cref="ConcurrentStack{T}"/>.</param> - /// <exception cref="ArgumentNullException"><paramref name="items"/> is a null reference - /// (Nothing in Visual Basic).</exception> - /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex"/> or <paramref - /// name="count"/> is negative. Or <paramref name="startIndex"/> is greater than or equal to the length - /// of <paramref name="items"/>.</exception> - /// <exception cref="ArgumentException"><paramref name="startIndex"/> + <paramref name="count"/> is - /// greater than the length of <paramref name="items"/>.</exception> - /// <remarks> - /// When adding multiple items to the stack, using PushRange is a more efficient - /// mechanism than using <see cref="Push"/> one item at a time. Additionally, PushRange - /// guarantees that all of the elements will be added atomically, meaning that no other threads will - /// be able to inject elements between the elements being pushed. Items at lower indices in the - /// <paramref name="items"/> array will be pushed before items at higher indices. - /// </remarks> - public void PushRange(T[] items, int startIndex, int count) - { - ValidatePushPopRangeInput(items, startIndex, count); - - // No op if the count is zero - if (count == 0) - return; - - - Node head, tail; - head = tail = new Node(items[startIndex]); - for (int i = startIndex + 1; i < startIndex + count; i++) - { - Node node = new Node(items[i]); - node.m_next = head; - head = node; - } - - tail.m_next = m_head; - if (Interlocked.CompareExchange(ref m_head, head, tail.m_next) == tail.m_next) - { - return; - } - - // If we failed, go to the slow path and loop around until we succeed. - PushCore(head, tail); - - } - /// <summary> /// Push one or many nodes into the stack, if head and tails are equal then push one node to the stack other wise push the list between head @@ -402,73 +261,6 @@ namespace System.Collections.Concurrent } /// <summary> - /// Local helper function to validate the Pop Push range methods input - /// </summary> - private void ValidatePushPopRangeInput(T[] items, int startIndex, int count) - { - if (items == null) - { - throw new ArgumentNullException(nameof(items)); - } - if (count < 0) - { - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ConcurrentStack_PushPopRange_CountOutOfRange")); - } - int length = items.Length; - if (startIndex >= length || startIndex < 0) - { - throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ConcurrentStack_PushPopRange_StartOutOfRange")); - } - if (length - count < startIndex) //instead of (startIndex + count > items.Length) to prevent overflow - { - throw new ArgumentException(Environment.GetResourceString("ConcurrentStack_PushPopRange_InvalidCount")); - } - } - - /// <summary> - /// Attempts to add an object to the <see - /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>. - /// </summary> - /// <param name="item">The object to add to the <see - /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>. |