From 5065ff34991bc3345e97cb9199dffe27555aede7 Mon Sep 17 00:00:00 2001 From: Oleksiy Gapotchenko Date: Wed, 8 Apr 2020 21:51:01 +0300 Subject: [PATCH 01/11] Update README.md --- .../README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Gapotchenko.FX.Runtime.CompilerServices.Intrinsics/README.md b/Source/Gapotchenko.FX.Runtime.CompilerServices.Intrinsics/README.md index 1c4475d1..5bd49749 100644 --- a/Source/Gapotchenko.FX.Runtime.CompilerServices.Intrinsics/README.md +++ b/Source/Gapotchenko.FX.Runtime.CompilerServices.Intrinsics/README.md @@ -71,8 +71,8 @@ using just a small fraction of cycles. Chances are your machine runs on a descendant of that influential CPU, be it AMD Ryzen or Intel Core. So how can we use the `BSR` instruction from .NET? -This is why `Gapotchenko.FX.Runtime.CompilerServices.Intrinsics` class was created. -It allows to provide an intrinsic implementation of a method with `MachineCodeIntrinsicAttribute`. Let's see how: +This is why `Gapotchenko.FX.Runtime.CompilerServices.Intrinsics` class exists. +It provides an ability to define intrinsic implementation of a method with `MachineCodeIntrinsicAttribute`. Let's see how: ``` csharp using Gapotchenko.FX.Runtime.CompilerServices; From 3041f405881f6ce9becae2e58dfb834f5fc629a0 Mon Sep 17 00:00:00 2001 From: Oleksiy Gapotchenko Date: Wed, 8 Apr 2020 21:55:48 +0300 Subject: [PATCH 02/11] Update README.md --- .../README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Gapotchenko.FX.Runtime.CompilerServices.Intrinsics/README.md b/Source/Gapotchenko.FX.Runtime.CompilerServices.Intrinsics/README.md index 5bd49749..72006a4f 100644 --- a/Source/Gapotchenko.FX.Runtime.CompilerServices.Intrinsics/README.md +++ b/Source/Gapotchenko.FX.Runtime.CompilerServices.Intrinsics/README.md @@ -110,7 +110,8 @@ class BitOperations `Log2_Intrinsic` method defines a custom attribute that provides a machine code for `BSR EAX, ECX` instruction. Machine code is tied to CPU architecture and this is reflected in the attribute as well. -`BitOperations` class now has a static constructor that ensures that intrinsic methods of the type are initialized (compiled) before they are used. +Please note that besides using `MachineCodeIntrinsicAttribute` to define method intrinsic implementations, +`BitOperations` class **should** use a static constructor to ensure that corresponding methods are initialized (compiled) before they are called. Here are the execution times of those implementations (lower is better): From 6662d6ebbaad1a6b5c1091d2c19824f62fd74fe2 Mon Sep 17 00:00:00 2001 From: Oleksiy Gapotchenko Date: Wed, 8 Apr 2020 21:56:51 +0300 Subject: [PATCH 03/11] Update README.md --- .../README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Gapotchenko.FX.Runtime.CompilerServices.Intrinsics/README.md b/Source/Gapotchenko.FX.Runtime.CompilerServices.Intrinsics/README.md index 72006a4f..94e323d2 100644 --- a/Source/Gapotchenko.FX.Runtime.CompilerServices.Intrinsics/README.md +++ b/Source/Gapotchenko.FX.Runtime.CompilerServices.Intrinsics/README.md @@ -113,7 +113,7 @@ Machine code is tied to CPU architecture and this is reflected in the attribute Please note that besides using `MachineCodeIntrinsicAttribute` to define method intrinsic implementations, `BitOperations` class **should** use a static constructor to ensure that corresponding methods are initialized (compiled) before they are called. -Here are the execution times of those implementations (lower is better): +Here are the execution times of all three implementations (lower is better): | Method | Mean | Error | StdDev | |--------------- |---------:|----------:|----------:| From 12c36dee9facaa4ee6e2cd78f084ff1966152bbc Mon Sep 17 00:00:00 2001 From: Oleksiy Gapotchenko Date: Wed, 8 Apr 2020 22:04:33 +0300 Subject: [PATCH 04/11] Update README.md --- .../README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Gapotchenko.FX.Runtime.CompilerServices.Intrinsics/README.md b/Source/Gapotchenko.FX.Runtime.CompilerServices.Intrinsics/README.md index 94e323d2..fa9a5d57 100644 --- a/Source/Gapotchenko.FX.Runtime.CompilerServices.Intrinsics/README.md +++ b/Source/Gapotchenko.FX.Runtime.CompilerServices.Intrinsics/README.md @@ -81,6 +81,7 @@ using System.Runtime.InteropServices; class BitOperations { + // Use static constructor to ensure that intrinsic methods are initialized (compiled) before they are called static BitOperations() => Intrinsics.InitializeType(typeof(BitOperations)); static readonly int[] m_Log2DeBruijn32 = @@ -91,6 +92,7 @@ class BitOperations 19, 27, 23, 6, 26, 5, 4, 31 }; + // Define machine code intrinsic for the method [MachineCodeIntrinsic(Architecture.X64, 0x0f, 0xbd, 0xc1)] // BSR EAX, ECX [MethodImpl(MethodImplOptions.NoInlining)] public static int Log2_Intrinsic(uint value) From 72a2906a45949e8acf08d4a813da40c48c34fb44 Mon Sep 17 00:00:00 2001 From: Oleksiy Gapotchenko Date: Sun, 12 Apr 2020 15:07:06 +0300 Subject: [PATCH 05/11] Update README.md --- Source/Gapotchenko.FX.Reflection.Loader/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Gapotchenko.FX.Reflection.Loader/README.md b/Source/Gapotchenko.FX.Reflection.Loader/README.md index 3df6969a..ed7867ff 100644 --- a/Source/Gapotchenko.FX.Reflection.Loader/README.md +++ b/Source/Gapotchenko.FX.Reflection.Loader/README.md @@ -222,7 +222,7 @@ The redirects are automatically created by build tools, and then put to correspo Assembly binding redirects work well for apps, but get completely broken if you want to employ them for dynamically loaded assemblies like plugins. The default .NET loader simply ignores `.config` files of .DLL assemblies! -`Gapotchenko.FX.Reflection.Loader` solves this. Just add the following code early at the assembly lifecycle: +`Gapotchenko.FX.Reflection.Loader` solves this. Just add the following code to a place which gets executed at the early stage of the assembly lifecycle: ``` csharp AssemblyLoader.Activate() @@ -268,7 +268,7 @@ In this way, the default .NET assembly loader can always load the assembly despi Another point to consider is **how to select a point of assembly loader installation** that is early enough in the assembly lifecycle. This tends to be trivial for an app: the first few lines of main entry point are good to go. -But it may be hard to do or totally infeasible for a class library with a wide public API surface. +But it may be hard to do, or even totally infeasible for a class library with a wide public API surface. To overcome that dilemma, assembly loader can be installed at module initializer of a class library. [Fody/ModuleInit](https://github.com/Fody/ModuleInit) is an example of tool that gives access to .NET module initialization functionality from high-level programming languages like C#/VB.NET. From 2aab4c7569f564313650c17434d3c086bff0a1a5 Mon Sep 17 00:00:00 2001 From: Oleksiy Gapotchenko Date: Sun, 12 Apr 2020 15:10:09 +0300 Subject: [PATCH 06/11] Update README.md --- Source/Gapotchenko.FX.Reflection.Loader/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Gapotchenko.FX.Reflection.Loader/README.md b/Source/Gapotchenko.FX.Reflection.Loader/README.md index ed7867ff..8cda7fd3 100644 --- a/Source/Gapotchenko.FX.Reflection.Loader/README.md +++ b/Source/Gapotchenko.FX.Reflection.Loader/README.md @@ -267,8 +267,8 @@ This is done to avoid chicken & egg dilemma. In this way, the default .NET assembly loader can always load the assembly despite the possible variety of different NuGet packages that can be used in the given project. Another point to consider is **how to select a point of assembly loader installation** that is early enough in the assembly lifecycle. -This tends to be trivial for an app: the first few lines of main entry point are good to go. -But it may be hard to do, or even totally infeasible for a class library with a wide public API surface. +This tends to be trivial for an app: the first few lines of the main entry point are good to go. +But it may be hard to do for a class library. Sometimes it gets totally infeasible when public API surface of a library gets wide enough. To overcome that dilemma, assembly loader can be installed at module initializer of a class library. [Fody/ModuleInit](https://github.com/Fody/ModuleInit) is an example of tool that gives access to .NET module initialization functionality from high-level programming languages like C#/VB.NET. From c8b7f2c67bc41eafc797a10e1e9ae509fd613cfa Mon Sep 17 00:00:00 2001 From: Oleksiy Gapotchenko Date: Sun, 12 Apr 2020 15:14:12 +0300 Subject: [PATCH 07/11] Update README.md --- Source/Gapotchenko.FX.Reflection.Loader/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Gapotchenko.FX.Reflection.Loader/README.md b/Source/Gapotchenko.FX.Reflection.Loader/README.md index 8cda7fd3..b0053d38 100644 --- a/Source/Gapotchenko.FX.Reflection.Loader/README.md +++ b/Source/Gapotchenko.FX.Reflection.Loader/README.md @@ -271,7 +271,7 @@ This tends to be trivial for an app: the first few lines of the main entry point But it may be hard to do for a class library. Sometimes it gets totally infeasible when public API surface of a library gets wide enough. To overcome that dilemma, assembly loader can be installed at module initializer of a class library. -[Fody/ModuleInit](https://github.com/Fody/ModuleInit) is an example of tool that gives access to .NET module initialization functionality from high-level programming languages like C#/VB.NET. +[Fody/ModuleInit](https://github.com/Fody/ModuleInit) is an example of tool that gives access to .NET module initialization functionality from high-level programming languages like C#/VB.NET. Another option is to use more specialized tool like [Eazfuscator.NET](https://www.gapotchenko.com/eazfuscator.net) that provides not only [module initialization functionality](https://help.gapotchenko.com/eazfuscator.net/63/sensei-features/module-initializers), but also intellectual property protectiion.
From c5cebce05b6c94e157c2f287965606748ec6df1e Mon Sep 17 00:00:00 2001 From: Oleksiy Gapotchenko Date: Sun, 12 Apr 2020 15:16:39 +0300 Subject: [PATCH 08/11] Update README.md --- Source/Gapotchenko.FX.Reflection.Loader/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Gapotchenko.FX.Reflection.Loader/README.md b/Source/Gapotchenko.FX.Reflection.Loader/README.md index b0053d38..f9d05e9a 100644 --- a/Source/Gapotchenko.FX.Reflection.Loader/README.md +++ b/Source/Gapotchenko.FX.Reflection.Loader/README.md @@ -271,7 +271,7 @@ This tends to be trivial for an app: the first few lines of the main entry point But it may be hard to do for a class library. Sometimes it gets totally infeasible when public API surface of a library gets wide enough. To overcome that dilemma, assembly loader can be installed at module initializer of a class library. -[Fody/ModuleInit](https://github.com/Fody/ModuleInit) is an example of tool that gives access to .NET module initialization functionality from high-level programming languages like C#/VB.NET. Another option is to use more specialized tool like [Eazfuscator.NET](https://www.gapotchenko.com/eazfuscator.net) that provides not only [module initialization functionality](https://help.gapotchenko.com/eazfuscator.net/63/sensei-features/module-initializers), but also intellectual property protectiion. +[Fody/ModuleInit](https://github.com/Fody/ModuleInit) is an example of tool that gives access to .NET module initialization functionality from high-level programming languages like C#/VB.NET. Another option is to use more specialized tool like [Eazfuscator.NET](https://www.gapotchenko.com/eazfuscator.net) that provides not only [module initialization functionality](https://help.gapotchenko.com/eazfuscator.net/63/sensei-features/module-initializers), but also intellectual property protection.
From 2ff0e98c1a6b0e9a5f3e779d6dc7e33bac29d5a0 Mon Sep 17 00:00:00 2001 From: Oleksiy Gapotchenko Date: Fri, 12 Jun 2020 13:41:25 +0300 Subject: [PATCH 09/11] Update README.md --- Source/Gapotchenko.FX.Reflection.Loader/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Gapotchenko.FX.Reflection.Loader/README.md b/Source/Gapotchenko.FX.Reflection.Loader/README.md index f9d05e9a..a1032884 100644 --- a/Source/Gapotchenko.FX.Reflection.Loader/README.md +++ b/Source/Gapotchenko.FX.Reflection.Loader/README.md @@ -255,7 +255,7 @@ namespace MyPlugin ``` There are a lot of projects that may need this: T4 templates, MSBuild tasks, plugins, extensions etc. -Basically everything that gets dynamically loaded and depends on one or more NuGet packages. +Basically everything that gets dynamically loaded and depends on one or more NuGet packages with mishmash of versions.
From 6e70341a564d90fc905eda3c5faa40a6326b8253 Mon Sep 17 00:00:00 2001 From: Oleksiy Gapotchenko Date: Fri, 12 Jun 2020 13:45:21 +0300 Subject: [PATCH 10/11] Update README.md --- Source/Gapotchenko.FX.Text/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Gapotchenko.FX.Text/README.md b/Source/Gapotchenko.FX.Text/README.md index e022fbaa..16f499d3 100644 --- a/Source/Gapotchenko.FX.Text/README.md +++ b/Source/Gapotchenko.FX.Text/README.md @@ -48,7 +48,7 @@ That's why `Gapotchenko.FX.Text` module provides a set of so called regex trampo They look exactly like `Equals`, `StartsWith`, `EndsWith`, `IndexOf` but work on regex patterns instead of raw strings. They also end with `Regex` suffix in their names, so `Equals` becomes `EqualsRegex`, `StartsWith` becomes `StartsWithRegex` and so on. -This is how a regex trampoline can be used for the given sample to meet the new requirements by a one-line change: +This is how a regex trampoline can be used for the given sample in order to meet the new requirements by a one-line change: ``` csharp using Gapotchenko.FX.Text.RegularExpressions; From 956197ab75c925c269558959b121360522de7fb4 Mon Sep 17 00:00:00 2001 From: Oleksiy Gapotchenko Date: Fri, 12 Jun 2020 20:38:27 +0300 Subject: [PATCH 11/11] Improved inline documentation. --- Source/Gapotchenko.FX/Optional`1.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Source/Gapotchenko.FX/Optional`1.cs b/Source/Gapotchenko.FX/Optional`1.cs index b4c44f18..5fdfd105 100644 --- a/Source/Gapotchenko.FX/Optional`1.cs +++ b/Source/Gapotchenko.FX/Optional`1.cs @@ -8,8 +8,12 @@ namespace Gapotchenko.FX { /// + /// /// Represents an optional value. - /// It is similar to , but can also operate with a value of a reference type. + /// + /// + /// is similar to but can also operate when is a reference type. + /// /// /// The underlying type of the generic type. [Serializable]