Commit de41b0e6 authored by Marc Gravell's avatar Marc Gravell

Use RunContinuationsAsynchronously when PLAT_SAFE_CONTINUATIONS is defined (NET46, DNXCORE50, etc)

parent 2bca2a52
...@@ -20,9 +20,12 @@ ...@@ -20,9 +20,12 @@
</group> </group>
<group targetFramework="net45"> <group targetFramework="net45">
</group> </group>
<group targetFramework="net46">
</group>
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>
<file src="StackExchange.Redis_Net46\bin.snk\Release\StackExchange.Redis*.*" target="lib\net46" />
<file src="StackExchange.Redis\bin.snk\Release\StackExchange.Redis*.*" target="lib\net45" /> <file src="StackExchange.Redis\bin.snk\Release\StackExchange.Redis*.*" target="lib\net45" />
<file src="StackExchange.Redis_Net40\bin.snk\Release\StackExchange.Redis*.*" target="lib\net40" /> <file src="StackExchange.Redis_Net40\bin.snk\Release\StackExchange.Redis*.*" target="lib\net40" />
</files> </files>
......
...@@ -9,24 +9,26 @@ ...@@ -9,24 +9,26 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>StackExchange.Redis.Tests</RootNamespace> <RootNamespace>StackExchange.Redis.Tests</RootNamespace>
<AssemblyName>StackExchange.Redis.Tests</AssemblyName> <AssemblyName>StackExchange.Redis.Tests</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath> <OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>TRACE;DEBUG;PLAT_SAFE_CONTINUATIONS</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath> <OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE;PLAT_SAFE_CONTINUATIONS</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
...@@ -139,13 +141,13 @@ ...@@ -139,13 +141,13 @@
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\StackExchange.Redis\StackExchange.Redis.csproj"> <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
<Project>{7cec07f2-8c03-4c42-b048-738b215824c1}</Project>
<Name>StackExchange.Redis</Name>
</ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> <ProjectReference Include="..\StackExchange.Redis_Net46\StackExchange.Redis_Net46.csproj">
<Project>{8c473a6f-b0de-4add-88f8-c41b441e407c}</Project>
<Name>StackExchange.Redis_Net46</Name>
</ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
......
...@@ -9,6 +9,8 @@ namespace StackExchange.Redis.Tests ...@@ -9,6 +9,8 @@ namespace StackExchange.Redis.Tests
public class TaskTests public class TaskTests
{ {
#if DEBUG #if DEBUG
#if !PLAT_SAFE_CONTINUATIONS // IsSyncSafe doesn't exist if PLAT_SAFE_CONTINUATIONS is defined
[Test] [Test]
[TestCase(SourceOrign.NewTCS, false)] [TestCase(SourceOrign.NewTCS, false)]
[TestCase(SourceOrign.Create, false)] [TestCase(SourceOrign.Create, false)]
...@@ -18,7 +20,7 @@ public void VerifyIsSyncSafe(SourceOrign origin, bool expected) ...@@ -18,7 +20,7 @@ public void VerifyIsSyncSafe(SourceOrign origin, bool expected)
var source = Create<int>(origin); var source = Create<int>(origin);
Assert.AreEqual(expected, TaskSource.IsSyncSafe(source.Task)); Assert.AreEqual(expected, TaskSource.IsSyncSafe(source.Task));
} }
#endif
static TaskCompletionSource<T> Create<T>(SourceOrign origin) static TaskCompletionSource<T> Create<T>(SourceOrign origin)
{ {
switch (origin) switch (origin)
......
...@@ -20,9 +20,12 @@ ...@@ -20,9 +20,12 @@
</group> </group>
<group targetFramework="net45"> <group targetFramework="net45">
</group> </group>
<group targetFramework="net46">
</group>
</dependencies> </dependencies>
</metadata> </metadata>
<files> <files>
<file src="StackExchange.Redis_Net46\bin\Release\StackExchange.Redis*.*" target="lib\net46" />
<file src="StackExchange.Redis\bin\Release\StackExchange.Redis*.*" target="lib\net45" /> <file src="StackExchange.Redis\bin\Release\StackExchange.Redis*.*" target="lib\net45" />
<file src="StackExchange.Redis_Net40\bin\Release\StackExchange.Redis*.*" target="lib\net40" /> <file src="StackExchange.Redis_Net40\bin\Release\StackExchange.Redis*.*" target="lib\net40" />
</files> </files>
......
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14 # Visual Studio 14
VisualStudioVersion = 14.0.23107.0 VisualStudioVersion = 14.0.24606.1
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis", "StackExchange.Redis\StackExchange.Redis.csproj", "{7CEC07F2-8C03-4C42-B048-738B215824C1}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis", "StackExchange.Redis\StackExchange.Redis.csproj", "{7CEC07F2-8C03-4C42-B048-738B215824C1}"
EndProject EndProject
...@@ -56,6 +56,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis.StrongN ...@@ -56,6 +56,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis.StrongN
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis_Net40.StrongName", "StackExchange.Redis_Net40\StackExchange.Redis_Net40.StrongName.csproj", "{75CED009-AAC6-4AC1-9C38-A0530619062D}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis_Net40.StrongName", "StackExchange.Redis_Net40\StackExchange.Redis_Net40.StrongName.csproj", "{75CED009-AAC6-4AC1-9C38-A0530619062D}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis_Net46", "StackExchange.Redis_Net46\StackExchange.Redis_Net46.csproj", "{8C473A6F-B0DE-4ADD-88F8-C41B441E407C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StackExchange.Redis_Net46.StrongName", "StackExchange.Redis_Net46\StackExchange.Redis_Net46.StrongName.csproj", "{8CE5D027-E332-42DD-BA54-16310DCD529C}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
...@@ -155,6 +159,26 @@ Global ...@@ -155,6 +159,26 @@ Global
{75CED009-AAC6-4AC1-9C38-A0530619062D}.Release|Any CPU.Build.0 = Release|Any CPU {75CED009-AAC6-4AC1-9C38-A0530619062D}.Release|Any CPU.Build.0 = Release|Any CPU
{75CED009-AAC6-4AC1-9C38-A0530619062D}.Verbose|Any CPU.ActiveCfg = Release|Any CPU {75CED009-AAC6-4AC1-9C38-A0530619062D}.Verbose|Any CPU.ActiveCfg = Release|Any CPU
{75CED009-AAC6-4AC1-9C38-A0530619062D}.Verbose|Any CPU.Build.0 = Release|Any CPU {75CED009-AAC6-4AC1-9C38-A0530619062D}.Verbose|Any CPU.Build.0 = Release|Any CPU
{8C473A6F-B0DE-4ADD-88F8-C41B441E407C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8C473A6F-B0DE-4ADD-88F8-C41B441E407C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8C473A6F-B0DE-4ADD-88F8-C41B441E407C}.Log Output|Any CPU.ActiveCfg = Mono|Any CPU
{8C473A6F-B0DE-4ADD-88F8-C41B441E407C}.Log Output|Any CPU.Build.0 = Mono|Any CPU
{8C473A6F-B0DE-4ADD-88F8-C41B441E407C}.Mono|Any CPU.ActiveCfg = Mono|Any CPU
{8C473A6F-B0DE-4ADD-88F8-C41B441E407C}.Mono|Any CPU.Build.0 = Mono|Any CPU
{8C473A6F-B0DE-4ADD-88F8-C41B441E407C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8C473A6F-B0DE-4ADD-88F8-C41B441E407C}.Release|Any CPU.Build.0 = Release|Any CPU
{8C473A6F-B0DE-4ADD-88F8-C41B441E407C}.Verbose|Any CPU.ActiveCfg = Mono|Any CPU
{8C473A6F-B0DE-4ADD-88F8-C41B441E407C}.Verbose|Any CPU.Build.0 = Mono|Any CPU
{8CE5D027-E332-42DD-BA54-16310DCD529C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8CE5D027-E332-42DD-BA54-16310DCD529C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8CE5D027-E332-42DD-BA54-16310DCD529C}.Log Output|Any CPU.ActiveCfg = Mono|Any CPU
{8CE5D027-E332-42DD-BA54-16310DCD529C}.Log Output|Any CPU.Build.0 = Mono|Any CPU
{8CE5D027-E332-42DD-BA54-16310DCD529C}.Mono|Any CPU.ActiveCfg = Mono|Any CPU
{8CE5D027-E332-42DD-BA54-16310DCD529C}.Mono|Any CPU.Build.0 = Mono|Any CPU
{8CE5D027-E332-42DD-BA54-16310DCD529C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8CE5D027-E332-42DD-BA54-16310DCD529C}.Release|Any CPU.Build.0 = Release|Any CPU
{8CE5D027-E332-42DD-BA54-16310DCD529C}.Verbose|Any CPU.ActiveCfg = Mono|Any CPU
{8CE5D027-E332-42DD-BA54-16310DCD529C}.Verbose|Any CPU.Build.0 = Mono|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
......
...@@ -100,7 +100,9 @@ public override bool TryComplete(bool isAsync) ...@@ -100,7 +100,9 @@ public override bool TryComplete(bool isAsync)
if (stateOrCompletionSource is TaskCompletionSource<T>) if (stateOrCompletionSource is TaskCompletionSource<T>)
{ {
var tcs = (TaskCompletionSource<T>)stateOrCompletionSource; var tcs = (TaskCompletionSource<T>)stateOrCompletionSource;
#if !PLAT_SAFE_CONTINUATIONS // we don't need to check in this scenario
if (isAsync || TaskSource.IsSyncSafe(tcs.Task)) if (isAsync || TaskSource.IsSyncSafe(tcs.Task))
#endif
{ {
T val; T val;
Exception ex; Exception ex;
...@@ -117,10 +119,12 @@ public override bool TryComplete(bool isAsync) ...@@ -117,10 +119,12 @@ public override bool TryComplete(bool isAsync)
} }
return true; return true;
} }
#if !PLAT_SAFE_CONTINUATIONS
else else
{ // looks like continuations; push to async to preserve the reader thread { // looks like continuations; push to async to preserve the reader thread
return false; return false;
} }
#endif
} }
else else
{ {
......
...@@ -16,6 +16,12 @@ namespace StackExchange.Redis ...@@ -16,6 +16,12 @@ namespace StackExchange.Redis
#endif #endif
static class TaskSource static class TaskSource
{ {
#if !PLAT_SAFE_CONTINUATIONS
// on .NET < 4.6, it was possible to have threads hijacked; this is no longer a problem in 4.6 and core-clr 5,
// thanks to the new TaskCreationOptions.RunContinuationsAsynchronously, however we still need to be a little
// "test and react", as we could be targeting 4.5 but running on a 4.6 machine, in which case *it can still
// work the magic* (thanks to over-the-top install)
/// <summary> /// <summary>
/// Indicates whether the specified task will not hijack threads when results are set /// Indicates whether the specified task will not hijack threads when results are set
/// </summary> /// </summary>
...@@ -59,7 +65,7 @@ static TaskSource() ...@@ -59,7 +65,7 @@ static TaskSource()
tcs.Task.ContinueWith(delegate { }); tcs.Task.ContinueWith(delegate { });
bool expectFalse = IsSyncSafe(tcs.Task); bool expectFalse = IsSyncSafe(tcs.Task);
tcs.SetResult(0); tcs.SetResult(0);
if(!expectTrue || expectFalse) if (!expectTrue || expectFalse)
{ {
Debug.WriteLine("IsSyncSafe reported incorrectly!"); Debug.WriteLine("IsSyncSafe reported incorrectly!");
Trace.WriteLine("IsSyncSafe reported incorrectly!"); Trace.WriteLine("IsSyncSafe reported incorrectly!");
...@@ -68,7 +74,7 @@ static TaskSource() ...@@ -68,7 +74,7 @@ static TaskSource()
} }
} }
} }
catch(Exception ex) catch (Exception ex)
{ {
Debug.WriteLine(ex.Message); Debug.WriteLine(ex.Message);
Trace.WriteLine(ex.Message); Trace.WriteLine(ex.Message);
...@@ -77,13 +83,17 @@ static TaskSource() ...@@ -77,13 +83,17 @@ static TaskSource()
if (IsSyncSafe == null) if (IsSyncSafe == null)
IsSyncSafe = t => false; // assume: not IsSyncSafe = t => false; // assume: not
} }
#endif
/// <summary> /// <summary>
/// Create a new TaskCompletion source /// Create a new TaskCompletion source
/// </summary> /// </summary>
public static TaskCompletionSource<T> Create<T>(object asyncState) public static TaskCompletionSource<T> Create<T>(object asyncState)
{ {
return new TaskCompletionSource<T>(asyncState); #if PLAT_SAFE_CONTINUATIONS
return new TaskCompletionSource<T>(asyncState, TaskCreationOptions.RunContinuationsAsynchronously);
#else
return new TaskCompletionSource<T>(asyncState, TaskCreationOptions.None);
#endif
} }
/// <summary> /// <summary>
......
This diff is collapsed.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.6.10.0" newVersion="2.6.10.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.6.10.0" newVersion="2.6.10.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/></startup></configuration>
<?xml version="1.0" encoding="utf-8"?>
<packages>
</packages>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment