Fix corner case error handling (#505)

This change fixes a corner case where we could orphan a call if an async call was started after a queue was terminated.
This commit is contained in:
Brian Pepin 2020-03-27 16:25:07 -07:00 коммит произвёл GitHub
Родитель 98e0c141d6
Коммит db4fb0c6c9
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
42 изменённых файлов: 584 добавлений и 182 удалений

Просмотреть файл

@ -158,6 +158,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\ThreadPool_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\referenced_ptr.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\WebSocket\WinRT\winrt_websocket.cpp" />

Просмотреть файл

@ -159,6 +159,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>

Просмотреть файл

@ -141,6 +141,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\ThreadPool_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\referenced_ptr.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\WebSocket\Websocketpp\websocketpp_websocket.cpp" />

Просмотреть файл

@ -138,6 +138,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
@ -183,46 +186,46 @@
</ItemGroup>
<ItemGroup>
<Filter Include="C++ Source">
<UniqueIdentifier>{B348936D-D09B-3ACE-A476-12C7C5E48781}</UniqueIdentifier>
<UniqueIdentifier>{AB68AAD7-BF0D-34C3-BFBA-FB7594810503}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Common">
<UniqueIdentifier>{6D290126-3831-3A04-903B-F2ADD104D81C}</UniqueIdentifier>
<UniqueIdentifier>{8B9EEA6A-3165-3A83-8CEB-648270B8C445}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Common\Win">
<UniqueIdentifier>{E705B256-E422-3FF4-95FA-7E24B8A5474F}</UniqueIdentifier>
<UniqueIdentifier>{28B59420-8446-3F26-9AB1-72123FF92816}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Global">
<UniqueIdentifier>{B5E18BF5-6C51-323C-96A0-81422D9D6069}</UniqueIdentifier>
<UniqueIdentifier>{A616C757-EB09-3284-8BA4-4C0B391C1672}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\HTTP">
<UniqueIdentifier>{6DAD9E7F-080C-3264-920E-77D0AFFE8CC9}</UniqueIdentifier>
<UniqueIdentifier>{7607E023-D56D-300A-AAE7-35C1337C6EF3}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\HTTP\WinHttp">
<UniqueIdentifier>{01466804-77B8-33C2-AAEE-469619C39927}</UniqueIdentifier>
<UniqueIdentifier>{6095F35A-0F36-3DA9-8D1A-8F2DA598B6E0}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Logger">
<UniqueIdentifier>{FD710BAD-78A2-39F4-9CB7-90B1627CC1D5}</UniqueIdentifier>
<UniqueIdentifier>{658327C4-885D-3CF1-9061-DA642B97898A}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Logger\Win">
<UniqueIdentifier>{CE716A57-F0D2-3112-9432-4955DE919940}</UniqueIdentifier>
<UniqueIdentifier>{89A6373D-D2E3-3B5B-B6CF-4AB7CDFB13B8}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Mock">
<UniqueIdentifier>{ECB59FD8-67C4-354A-90B2-DFC893C0F2E5}</UniqueIdentifier>
<UniqueIdentifier>{57AC3982-96A9-3B0B-A7DF-8DF69AD19ECC}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Task">
<UniqueIdentifier>{09ED63FC-76E4-368A-B7E4-40A1D70ABD31}</UniqueIdentifier>
<UniqueIdentifier>{075BEBE6-800C-3FB2-84E2-6443C472E199}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Task\Win">
<UniqueIdentifier>{82CDC498-C15D-38CB-ABAF-432B4881A142}</UniqueIdentifier>
<UniqueIdentifier>{D0B227E9-0B82-3AF7-82EC-9581DA9FD1A3}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\WebSocket">
<UniqueIdentifier>{09CB3AE4-1639-3274-BB94-99AAC498EA50}</UniqueIdentifier>
<UniqueIdentifier>{0974FCD6-8409-3FA3-A118-A58ED0FD041C}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\WebSocket\Win">
<UniqueIdentifier>{802954F0-B5AC-3B13-A5F2-01E8A7888AAE}</UniqueIdentifier>
<UniqueIdentifier>{350A88A7-908E-346C-8EEC-8C500141D764}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Public Includes">
<UniqueIdentifier>{42CA3718-AE3E-3CEB-A859-F23D0D7A9918}</UniqueIdentifier>
<UniqueIdentifier>{2F64C9BE-5116-3E71-971F-592C0D76A89D}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

Просмотреть файл

@ -130,6 +130,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\ThreadPool_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\referenced_ptr.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\WebSocket\WinRT\winrt_websocket.cpp" />

Просмотреть файл

@ -159,6 +159,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>

Просмотреть файл

@ -46,7 +46,6 @@
<ApplicationTypeRevision>3.0</ApplicationTypeRevision>
<HCLibPlatformType>Android</HCLibPlatformType>
<HCLibImpl>true</HCLibImpl>
<AndroidSdkBuildToolsVersion>25.0.3</AndroidSdkBuildToolsVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
@ -126,6 +125,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\ThreadPool_stl.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer_stl.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\referenced_ptr.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\WebSocket\Websocketpp\websocketpp_websocket.cpp" />

Просмотреть файл

@ -147,6 +147,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>

Просмотреть файл

@ -169,6 +169,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\ThreadPool_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\referenced_ptr.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\WebSocket\WinRT\winrt_websocket.cpp" />

Просмотреть файл

@ -159,6 +159,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>

Просмотреть файл

@ -150,6 +150,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\ThreadPool_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\referenced_ptr.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\WebSocket\Websocketpp\websocketpp_websocket.cpp" />

Просмотреть файл

@ -138,6 +138,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
@ -183,46 +186,46 @@
</ItemGroup>
<ItemGroup>
<Filter Include="C++ Source">
<UniqueIdentifier>{B348936D-D09B-3ACE-A476-12C7C5E48781}</UniqueIdentifier>
<UniqueIdentifier>{AB68AAD7-BF0D-34C3-BFBA-FB7594810503}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Common">
<UniqueIdentifier>{6D290126-3831-3A04-903B-F2ADD104D81C}</UniqueIdentifier>
<UniqueIdentifier>{8B9EEA6A-3165-3A83-8CEB-648270B8C445}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Common\Win">
<UniqueIdentifier>{E705B256-E422-3FF4-95FA-7E24B8A5474F}</UniqueIdentifier>
<UniqueIdentifier>{28B59420-8446-3F26-9AB1-72123FF92816}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Global">
<UniqueIdentifier>{B5E18BF5-6C51-323C-96A0-81422D9D6069}</UniqueIdentifier>
<UniqueIdentifier>{A616C757-EB09-3284-8BA4-4C0B391C1672}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\HTTP">
<UniqueIdentifier>{6DAD9E7F-080C-3264-920E-77D0AFFE8CC9}</UniqueIdentifier>
<UniqueIdentifier>{7607E023-D56D-300A-AAE7-35C1337C6EF3}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\HTTP\WinHttp">
<UniqueIdentifier>{01466804-77B8-33C2-AAEE-469619C39927}</UniqueIdentifier>
<UniqueIdentifier>{6095F35A-0F36-3DA9-8D1A-8F2DA598B6E0}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Logger">
<UniqueIdentifier>{FD710BAD-78A2-39F4-9CB7-90B1627CC1D5}</UniqueIdentifier>
<UniqueIdentifier>{658327C4-885D-3CF1-9061-DA642B97898A}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Logger\Win">
<UniqueIdentifier>{CE716A57-F0D2-3112-9432-4955DE919940}</UniqueIdentifier>
<UniqueIdentifier>{89A6373D-D2E3-3B5B-B6CF-4AB7CDFB13B8}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Mock">
<UniqueIdentifier>{ECB59FD8-67C4-354A-90B2-DFC893C0F2E5}</UniqueIdentifier>
<UniqueIdentifier>{57AC3982-96A9-3B0B-A7DF-8DF69AD19ECC}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Task">
<UniqueIdentifier>{09ED63FC-76E4-368A-B7E4-40A1D70ABD31}</UniqueIdentifier>
<UniqueIdentifier>{075BEBE6-800C-3FB2-84E2-6443C472E199}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Task\Win">
<UniqueIdentifier>{82CDC498-C15D-38CB-ABAF-432B4881A142}</UniqueIdentifier>
<UniqueIdentifier>{D0B227E9-0B82-3AF7-82EC-9581DA9FD1A3}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\WebSocket">
<UniqueIdentifier>{09CB3AE4-1639-3274-BB94-99AAC498EA50}</UniqueIdentifier>
<UniqueIdentifier>{0974FCD6-8409-3FA3-A118-A58ED0FD041C}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\WebSocket\Win">
<UniqueIdentifier>{802954F0-B5AC-3B13-A5F2-01E8A7888AAE}</UniqueIdentifier>
<UniqueIdentifier>{350A88A7-908E-346C-8EEC-8C500141D764}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Public Includes">
<UniqueIdentifier>{42CA3718-AE3E-3CEB-A859-F23D0D7A9918}</UniqueIdentifier>
<UniqueIdentifier>{2F64C9BE-5116-3E71-971F-592C0D76A89D}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

Просмотреть файл

@ -131,6 +131,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\ThreadPool_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\referenced_ptr.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\WebSocket\WinRT\winrt_websocket.cpp" />

Просмотреть файл

@ -159,6 +159,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>

Просмотреть файл

@ -35,7 +35,7 @@
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{5e0ce391-1ac5-4930-921e-2577a4b5c530}</ProjectGuid>
<ProjectGuid>{80FE2440-4F89-4A47-88C6-E86447BC2319}</ProjectGuid>
<Keyword>Android</Keyword>
<PlatformToolset>Clang_5_0</PlatformToolset>
<AndroidAPILevel Condition="'$(Platform)'!='ARM64' AND '$(Platform)'!='x64'">android-19</AndroidAPILevel>
@ -46,7 +46,6 @@
<ApplicationTypeRevision>3.0</ApplicationTypeRevision>
<HCLibPlatformType>Android</HCLibPlatformType>
<HCLibImpl>true</HCLibImpl>
<AndroidSdkBuildToolsVersion>25.0.3</AndroidSdkBuildToolsVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup>
@ -126,6 +125,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\ThreadPool_stl.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer_stl.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\referenced_ptr.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\WebSocket\Websocketpp\websocketpp_websocket.cpp" />

Просмотреть файл

@ -147,6 +147,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
@ -192,46 +195,46 @@
</ItemGroup>
<ItemGroup>
<Filter Include="C++ Source">
<UniqueIdentifier>{A740C412-FB5D-3AAA-8C89-79F901BDFCAA}</UniqueIdentifier>
<UniqueIdentifier>{AB68AAD7-BF0D-34C3-BFBA-FB7594810503}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Common">
<UniqueIdentifier>{27CFE030-22C9-3F80-BE9E-6C85269BA8CF}</UniqueIdentifier>
<UniqueIdentifier>{8B9EEA6A-3165-3A83-8CEB-648270B8C445}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Common\Android">
<UniqueIdentifier>{7F5C193A-6335-3652-8522-F362DE77CEC5}</UniqueIdentifier>
<UniqueIdentifier>{F6086770-20F5-36E7-9347-F8E511A64421}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Global">
<UniqueIdentifier>{3A5140CA-AFB5-3F07-934D-A8067647C112}</UniqueIdentifier>
<UniqueIdentifier>{A616C757-EB09-3284-8BA4-4C0B391C1672}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\HTTP">
<UniqueIdentifier>{4C46FCD2-8942-35E4-A9F6-E32517A218FC}</UniqueIdentifier>
<UniqueIdentifier>{7607E023-D56D-300A-AAE7-35C1337C6EF3}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\HTTP\Android">
<UniqueIdentifier>{3FE50A42-C399-35C5-807F-53541A10E202}</UniqueIdentifier>
<UniqueIdentifier>{15D2B7C4-8092-30BB-B45A-23FB8BB289F7}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Logger">
<UniqueIdentifier>{F9631A84-9D6B-300A-B12D-A52D1FCE33D5}</UniqueIdentifier>
<UniqueIdentifier>{658327C4-885D-3CF1-9061-DA642B97898A}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Logger\Android">
<UniqueIdentifier>{1CBA16A9-7A69-31BB-8A4F-0C4D1CC3CF66}</UniqueIdentifier>
<UniqueIdentifier>{5DE6DC08-DC97-3EDE-86DC-D80C73AB8212}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Mock">
<UniqueIdentifier>{7E7975B0-87A8-3B63-AC39-F4B973EBFE5E}</UniqueIdentifier>
<UniqueIdentifier>{57AC3982-96A9-3B0B-A7DF-8DF69AD19ECC}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Task">
<UniqueIdentifier>{A5C44A5C-F557-3485-B0F3-96924ED16997}</UniqueIdentifier>
<UniqueIdentifier>{075BEBE6-800C-3FB2-84E2-6443C472E199}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Task\Android">
<UniqueIdentifier>{B18AF8F5-F9A5-3AA5-BCEA-7699667F4BEF}</UniqueIdentifier>
<UniqueIdentifier>{B2E61810-6BF3-36DB-9286-C42708123F18}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\WebSocket">
<UniqueIdentifier>{0EAC292A-EAC0-3C04-9776-AA439EE69493}</UniqueIdentifier>
<UniqueIdentifier>{0974FCD6-8409-3FA3-A118-A58ED0FD041C}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\WebSocket\Android">
<UniqueIdentifier>{1B92AFE8-7559-338C-9B27-68248D7AF766}</UniqueIdentifier>
<UniqueIdentifier>{683D025C-B830-3477-9275-4EA8A76EDB09}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Public Includes">
<UniqueIdentifier>{D805E6E3-877C-379F-9EEB-B64746DE0E67}</UniqueIdentifier>
<UniqueIdentifier>{2F64C9BE-5116-3E71-971F-592C0D76A89D}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

Просмотреть файл

@ -169,6 +169,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\ThreadPool_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\referenced_ptr.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\WebSocket\WinRT\winrt_websocket.cpp" />
@ -188,4 +189,4 @@
<ItemGroup>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>

Просмотреть файл

@ -159,6 +159,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
@ -201,46 +204,46 @@
</ItemGroup>
<ItemGroup>
<Filter Include="C++ Source">
<UniqueIdentifier>{A740C412-FB5D-3AAA-8C89-79F901BDFCAA}</UniqueIdentifier>
<UniqueIdentifier>{AB68AAD7-BF0D-34C3-BFBA-FB7594810503}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Common">
<UniqueIdentifier>{27CFE030-22C9-3F80-BE9E-6C85269BA8CF}</UniqueIdentifier>
<UniqueIdentifier>{8B9EEA6A-3165-3A83-8CEB-648270B8C445}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Common\Win">
<UniqueIdentifier>{DFE90BE8-BA04-38D4-B957-489922F25F6C}</UniqueIdentifier>
<UniqueIdentifier>{28B59420-8446-3F26-9AB1-72123FF92816}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Global">
<UniqueIdentifier>{3A5140CA-AFB5-3F07-934D-A8067647C112}</UniqueIdentifier>
<UniqueIdentifier>{A616C757-EB09-3284-8BA4-4C0B391C1672}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\HTTP">
<UniqueIdentifier>{4C46FCD2-8942-35E4-A9F6-E32517A218FC}</UniqueIdentifier>
<UniqueIdentifier>{7607E023-D56D-300A-AAE7-35C1337C6EF3}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\HTTP\XMLHttp">
<UniqueIdentifier>{9BC3BA0D-F317-3F19-87DD-76A8B0C73BEF}</UniqueIdentifier>
<UniqueIdentifier>{E77621FA-48B7-342B-A48A-7652D1F73D57}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Logger">
<UniqueIdentifier>{F9631A84-9D6B-300A-B12D-A52D1FCE33D5}</UniqueIdentifier>
<UniqueIdentifier>{658327C4-885D-3CF1-9061-DA642B97898A}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Logger\Win">
<UniqueIdentifier>{42447043-740A-346F-BF7B-15D083F4D78C}</UniqueIdentifier>
<UniqueIdentifier>{89A6373D-D2E3-3B5B-B6CF-4AB7CDFB13B8}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Mock">
<UniqueIdentifier>{7E7975B0-87A8-3B63-AC39-F4B973EBFE5E}</UniqueIdentifier>
<UniqueIdentifier>{57AC3982-96A9-3B0B-A7DF-8DF69AD19ECC}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Task">
<UniqueIdentifier>{A5C44A5C-F557-3485-B0F3-96924ED16997}</UniqueIdentifier>
<UniqueIdentifier>{075BEBE6-800C-3FB2-84E2-6443C472E199}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Task\Win">
<UniqueIdentifier>{4075F186-2D52-323A-9287-AE69359740B8}</UniqueIdentifier>
<UniqueIdentifier>{D0B227E9-0B82-3AF7-82EC-9581DA9FD1A3}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\WebSocket">
<UniqueIdentifier>{0EAC292A-EAC0-3C04-9776-AA439EE69493}</UniqueIdentifier>
<UniqueIdentifier>{0974FCD6-8409-3FA3-A118-A58ED0FD041C}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\WebSocket\WinRT">
<UniqueIdentifier>{DA11A23D-43F8-30E7-A583-24AACCBE0501}</UniqueIdentifier>
<UniqueIdentifier>{E4F43182-9F97-3EBF-8BB9-4E51EB7E5C4D}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Public Includes">
<UniqueIdentifier>{D805E6E3-877C-379F-9EEB-B64746DE0E67}</UniqueIdentifier>
<UniqueIdentifier>{2F64C9BE-5116-3E71-971F-592C0D76A89D}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

Просмотреть файл

@ -150,6 +150,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\ThreadPool_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\referenced_ptr.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\WebSocket\Websocketpp\websocketpp_websocket.cpp" />

Просмотреть файл

@ -138,6 +138,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
@ -183,46 +186,46 @@
</ItemGroup>
<ItemGroup>
<Filter Include="C++ Source">
<UniqueIdentifier>{A740C412-FB5D-3AAA-8C89-79F901BDFCAA}</UniqueIdentifier>
<UniqueIdentifier>{AB68AAD7-BF0D-34C3-BFBA-FB7594810503}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Common">
<UniqueIdentifier>{27CFE030-22C9-3F80-BE9E-6C85269BA8CF}</UniqueIdentifier>
<UniqueIdentifier>{8B9EEA6A-3165-3A83-8CEB-648270B8C445}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Common\Win">
<UniqueIdentifier>{DFE90BE8-BA04-38D4-B957-489922F25F6C}</UniqueIdentifier>
<UniqueIdentifier>{28B59420-8446-3F26-9AB1-72123FF92816}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Global">
<UniqueIdentifier>{3A5140CA-AFB5-3F07-934D-A8067647C112}</UniqueIdentifier>
<UniqueIdentifier>{A616C757-EB09-3284-8BA4-4C0B391C1672}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\HTTP">
<UniqueIdentifier>{4C46FCD2-8942-35E4-A9F6-E32517A218FC}</UniqueIdentifier>
<UniqueIdentifier>{7607E023-D56D-300A-AAE7-35C1337C6EF3}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\HTTP\WinHttp">
<UniqueIdentifier>{B97A6D17-B3B3-3752-AFCE-0EC15FD7B2D2}</UniqueIdentifier>
<UniqueIdentifier>{6095F35A-0F36-3DA9-8D1A-8F2DA598B6E0}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Logger">
<UniqueIdentifier>{F9631A84-9D6B-300A-B12D-A52D1FCE33D5}</UniqueIdentifier>
<UniqueIdentifier>{658327C4-885D-3CF1-9061-DA642B97898A}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Logger\Win">
<UniqueIdentifier>{42447043-740A-346F-BF7B-15D083F4D78C}</UniqueIdentifier>
<UniqueIdentifier>{89A6373D-D2E3-3B5B-B6CF-4AB7CDFB13B8}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Mock">
<UniqueIdentifier>{7E7975B0-87A8-3B63-AC39-F4B973EBFE5E}</UniqueIdentifier>
<UniqueIdentifier>{57AC3982-96A9-3B0B-A7DF-8DF69AD19ECC}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Task">
<UniqueIdentifier>{A5C44A5C-F557-3485-B0F3-96924ED16997}</UniqueIdentifier>
<UniqueIdentifier>{075BEBE6-800C-3FB2-84E2-6443C472E199}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Task\Win">
<UniqueIdentifier>{4075F186-2D52-323A-9287-AE69359740B8}</UniqueIdentifier>
<UniqueIdentifier>{D0B227E9-0B82-3AF7-82EC-9581DA9FD1A3}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\WebSocket">
<UniqueIdentifier>{0EAC292A-EAC0-3C04-9776-AA439EE69493}</UniqueIdentifier>
<UniqueIdentifier>{0974FCD6-8409-3FA3-A118-A58ED0FD041C}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\WebSocket\Win">
<UniqueIdentifier>{35985716-80A2-3783-AE12-674A2189F43D}</UniqueIdentifier>
<UniqueIdentifier>{350A88A7-908E-346C-8EEC-8C500141D764}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Public Includes">
<UniqueIdentifier>{D805E6E3-877C-379F-9EEB-B64746DE0E67}</UniqueIdentifier>
<UniqueIdentifier>{2F64C9BE-5116-3E71-971F-592C0D76A89D}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

Просмотреть файл

@ -12,7 +12,7 @@
</ItemGroup>
<PropertyGroup Label="Globals">
<ApplicationEnvironment>title</ApplicationEnvironment>
<ProjectGuid>{9E0EB8C2-40CD-448F-9B98-DAF9830EF9AD}</ProjectGuid>
<ProjectGuid>{57C681F7-280F-45B8-9FA9-D556C24F2053}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<ProjectName>libHttpClient.142.XDK.C</ProjectName>
<RootNamespace>xbox.httpclient</RootNamespace>

Просмотреть файл

@ -201,46 +201,46 @@
</ItemGroup>
<ItemGroup>
<Filter Include="C++ Source">
<UniqueIdentifier>{A740C412-FB5D-3AAA-8C89-79F901BDFCAA}</UniqueIdentifier>
<UniqueIdentifier>{AB68AAD7-BF0D-34C3-BFBA-FB7594810503}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Common">
<UniqueIdentifier>{27CFE030-22C9-3F80-BE9E-6C85269BA8CF}</UniqueIdentifier>
<UniqueIdentifier>{8B9EEA6A-3165-3A83-8CEB-648270B8C445}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Common\Win">
<UniqueIdentifier>{DFE90BE8-BA04-38D4-B957-489922F25F6C}</UniqueIdentifier>
<UniqueIdentifier>{28B59420-8446-3F26-9AB1-72123FF92816}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Global">
<UniqueIdentifier>{3A5140CA-AFB5-3F07-934D-A8067647C112}</UniqueIdentifier>
<UniqueIdentifier>{A616C757-EB09-3284-8BA4-4C0B391C1672}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\HTTP">
<UniqueIdentifier>{4C46FCD2-8942-35E4-A9F6-E32517A218FC}</UniqueIdentifier>
<UniqueIdentifier>{7607E023-D56D-300A-AAE7-35C1337C6EF3}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\HTTP\XMLHttp">
<UniqueIdentifier>{9BC3BA0D-F317-3F19-87DD-76A8B0C73BEF}</UniqueIdentifier>
<UniqueIdentifier>{E77621FA-48B7-342B-A48A-7652D1F73D57}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Logger">
<UniqueIdentifier>{F9631A84-9D6B-300A-B12D-A52D1FCE33D5}</UniqueIdentifier>
<UniqueIdentifier>{658327C4-885D-3CF1-9061-DA642B97898A}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Logger\Win">
<UniqueIdentifier>{42447043-740A-346F-BF7B-15D083F4D78C}</UniqueIdentifier>
<UniqueIdentifier>{89A6373D-D2E3-3B5B-B6CF-4AB7CDFB13B8}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Mock">
<UniqueIdentifier>{7E7975B0-87A8-3B63-AC39-F4B973EBFE5E}</UniqueIdentifier>
<UniqueIdentifier>{57AC3982-96A9-3B0B-A7DF-8DF69AD19ECC}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Task">
<UniqueIdentifier>{A5C44A5C-F557-3485-B0F3-96924ED16997}</UniqueIdentifier>
<UniqueIdentifier>{075BEBE6-800C-3FB2-84E2-6443C472E199}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\Task\Win">
<UniqueIdentifier>{4075F186-2D52-323A-9287-AE69359740B8}</UniqueIdentifier>
<UniqueIdentifier>{D0B227E9-0B82-3AF7-82EC-9581DA9FD1A3}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\WebSocket">
<UniqueIdentifier>{0EAC292A-EAC0-3C04-9776-AA439EE69493}</UniqueIdentifier>
<UniqueIdentifier>{0974FCD6-8409-3FA3-A118-A58ED0FD041C}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Source\WebSocket\WinRT">
<UniqueIdentifier>{DA11A23D-43F8-30E7-A583-24AACCBE0501}</UniqueIdentifier>
<UniqueIdentifier>{E4F43182-9F97-3EBF-8BB9-4E51EB7E5C4D}</UniqueIdentifier>
</Filter>
<Filter Include="C++ Public Includes">
<UniqueIdentifier>{D805E6E3-877C-379F-9EEB-B64746DE0E67}</UniqueIdentifier>
<UniqueIdentifier>{2F64C9BE-5116-3E71-971F-592C0D76A89D}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -157,6 +157,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\ThreadPool_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\referenced_ptr.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\WebSocket\Unittest\websocket_unittest.cpp" />

Просмотреть файл

@ -159,6 +159,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>

Просмотреть файл

@ -221,6 +221,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\ThreadPool_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\referenced_ptr.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\WebSocket\Unittest\websocket_unittest.cpp" />

Просмотреть файл

@ -156,6 +156,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>

Просмотреть файл

@ -20,7 +20,7 @@
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>libHttpClient.UnitTest.142.TAEF</ProjectName>
<ProjectGuid>{EBFE0314-0869-46B8-ABCE-A3EE223893B8}</ProjectGuid>
<ProjectGuid>{9E0EB8C2-40CD-448F-9B98-DAF9830EF9AD}</ProjectGuid>
<RootNamespace>libHttpClient.Test</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.10240.0</WindowsTargetPlatformMinVersion>
@ -145,6 +145,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\ThreadPool_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\referenced_ptr.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\WebSocket\Unittest\websocket_unittest.cpp" />

Просмотреть файл

@ -159,6 +159,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>

Просмотреть файл

@ -221,6 +221,7 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\ThreadPool_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer_win32.cpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\referenced_ptr.h" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\..\Source\WebSocket\Unittest\websocket_unittest.cpp" />

Просмотреть файл

@ -156,6 +156,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\WaitTimer.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XAsyncProviderPriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)..\..\Source\Task\XTaskQueuePriv.h">
<Filter>C++ Source\Task</Filter>
</ClInclude>

Просмотреть файл

@ -113,36 +113,6 @@ STDAPI XAsyncBegin(
_In_ XAsyncProvider* provider
) noexcept;
/// <summary>
/// Initializes an async block for use. Once begun calls such
/// as XAsyncGetStatus will provide meaningful data. It is assumed the
/// async work will begin on some system defined thread after this call
/// returns. The token and function parameters can be used to help identify
/// mismatched Begin/GetResult calls. The token is typically the function
/// pointer of the async API you are implementing, and the functionName parameter
/// is typically the __FUNCTION__ compiler macro.
///
/// This variant of XAsyncBegin will allocate additional memory of size contextSize
/// and use this as the context pointer for async provider callbacks. The memory
/// pointer is returned in 'context'. The lifetime of this memory is managed
/// by the async library and will be freed automatically when the call
/// completes.
/// </summary>
/// <param name='asyncBlock'>A pointer to the XAsyncBlock that holds data for the call.</param>
/// <param name='identity'>An optional arbitrary pointer that can be used to identify this call.</param>
/// <param name='identityName'>An optional string that names the async call. This is typically the __FUNCTION__ compiler macro.</param>
/// <param name='provider'>The function callback to invoke to implement the async call.</param>
/// <param name='contextSize'>The size, in bytes, of additional context memory to allocate.</param>
/// <param name='context'>The allocated context object pointer.</param>
STDAPI XAsyncBeginAlloc(
_Inout_ XAsyncBlock* asyncBlock,
_In_opt_ const void* identity,
_In_opt_ const char* identityName,
_In_ XAsyncProvider* provider,
_In_ size_t contextSize,
_Out_ void** context
) noexcept;
/// <summary>
/// Schedules a callback to do async work. Calling this is optional. If the async work can be done
/// through a system - async mechanism like overlapped IO or async COM, there is no need to schedule

Просмотреть файл

@ -18,3 +18,5 @@
HC_TRACE_ERROR(HTTPCLIENT, fmt, ##__VA_ARGS__); \
ASSERT(false); \
#define FAIL_FAST_IF_FAILED(hr) do { HRESULT __hrRet = hr; if (FAILED(__hrRet)) { FAIL_FAST_MSG("%s 0x%08", #hr, __hrRet); }} while (0, 0)

Просмотреть файл

@ -27,6 +27,7 @@
#include <WinSock2.h>
#include <windows.h>
#include <objbase.h>
#else
#define __STDC_LIMIT_MACROS

Просмотреть файл

@ -2,6 +2,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#include "pch.h"
#include "XTaskQueuePriv.h"
#define ASYNC_BLOCK_SIG 0x41535942 // ASYB
#define ASYNC_STATE_SIG 0x41535445 // ASTE
@ -9,6 +10,9 @@
// Used by unit tests to verify we cleanup memory correctly.
std::atomic<uint32_t> s_AsyncLibGlobalStateCount{ 0 };
// Set externally to enable pumping waits.
bool s_AsyncLibEnablePumpingWait = false;
enum class ProviderCleanupLocation
{
Destructor,
@ -42,6 +46,10 @@ struct AsyncState
std::condition_variable waitCondition;
bool waitSatisfied = false;
#if _WIN32
HANDLE waitEvent = nullptr;
#endif
const void* identity = nullptr;
const char* identityName = nullptr;
@ -89,9 +97,17 @@ private:
if (queue != nullptr)
{
XTaskQueueResumeTermination(queue);
XTaskQueueCloseHandle(queue);
}
#if _WIN32
if (waitEvent != nullptr)
{
CloseHandle(waitEvent);
}
#endif
--s_AsyncLibGlobalStateCount;
}
};
@ -339,8 +355,8 @@ private:
static void CALLBACK CompletionCallback(_In_ void* context, _In_ bool canceled);
static void CALLBACK WorkerCallback(_In_ void* context, _In_ bool canceled);
static void SignalCompletion(_In_ AsyncStateRef const& state);
static void SignalWait(_In_ AsyncStateRef const& state);
static HRESULT SignalCompletion(_In_ AsyncStateRef const& state);
static HRESULT AllocStateNoCompletion(_Inout_ XAsyncBlock* asyncBlock, _Inout_ AsyncBlockInternal* internal, _In_ size_t contextSize);
static HRESULT AllocState(_Inout_ XAsyncBlock* asyncBlock, _In_ size_t contextSize);
static void CleanupState(_Inout_ AsyncStateRef&& state);
@ -368,9 +384,16 @@ static HRESULT AllocStateNoCompletion(_Inout_ XAsyncBlock* asyncBlock, _Inout_ A
{
RETURN_IF_FAILED(XTaskQueueDuplicateHandle(queue, &state->queue));
}
RETURN_IF_FAILED(XTaskQueueSuspendTermination(state->queue));
state->userAsyncBlock = asyncBlock;
state->providerData.async = &state->providerAsyncBlock;
#if _WIN32
state->waitEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
RETURN_LAST_ERROR_IF(state->waitEvent == nullptr);
#endif
internal->state = state.Detach();
@ -437,12 +460,14 @@ static void CleanupProviderForLocation(_Inout_ AsyncStateRef& state, _In_ Provid
}
}
static void SignalCompletion(_In_ AsyncStateRef const& state)
static HRESULT SignalCompletion(_In_ AsyncStateRef const& state)
{
HRESULT hr = S_OK;
if (state->providerData.async->callback != nullptr)
{
AsyncStateRef callbackState(state.Get());
HRESULT hr = XTaskQueueSubmitCallback(
hr = XTaskQueueSubmitCallback(
state->queue,
XTaskQueuePort::Completion,
callbackState.Get(),
@ -457,6 +482,8 @@ static void SignalCompletion(_In_ AsyncStateRef const& state)
{
SignalWait(state);
}
return hr;
}
static void SignalWait(_In_ AsyncStateRef const& state)
@ -465,6 +492,9 @@ static void SignalWait(_In_ AsyncStateRef const& state)
std::lock_guard<std::mutex> lock(state->waitMutex);
state->waitSatisfied = true;
}
#if _WIN32
SetEvent(state->waitEvent);
#endif
state->waitCondition.notify_all();
}
@ -501,8 +531,6 @@ static void CALLBACK WorkerCallback(
return;
}
bool completedNow = false;
// If the queue is canceling callbacks, simply cancel this work. Since no
// new work for this call will be scheduled, if the call didn't cancel
// immediately do it ourselves.
@ -536,20 +564,7 @@ static void CALLBACK WorkerCallback(
result = E_UNEXPECTED;
}
{
AsyncBlockInternalGuard internal{ &state->providerAsyncBlock };
completedNow = internal.TrySetTerminalStatus(result);
if (completedNow)
{
internal.ExtractState();
}
}
if (completedNow)
{
SignalCompletion(state);
}
XAsyncComplete(&state->providerAsyncBlock, result, 0);
}
}
@ -557,11 +572,6 @@ static void CALLBACK WorkerCallback(
// will change the provider cleanup to be "AfterWork", which is here. Cleanup
// the provider if we need to.
CleanupProviderForLocation(state, ProviderCleanupLocation::AfterDoWork);
if (completedNow)
{
CleanupState(std::move(state));
}
}
//
@ -600,6 +610,27 @@ STDAPI XAsyncGetStatus(
}
else
{
// This codebase compiles for multiple platforms on GitHub. This is only
// supported on win32 desktop platforms. It is enabled for Windows builds.
#if _WIN32
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
// If we're being asked to wait from a STA thread, use a CoWait to ensure we
// don't totally gum up the thread. Then fall back to our normal condition
// variable check (both are signaled during completion).
if (s_AsyncLibEnablePumpingWait)
{
APTTYPE aptType;
APTTYPEQUALIFIER aptQualifier;
if (SUCCEEDED(CoGetApartmentType(&aptType, &aptQualifier)) && aptType != APTTYPE_MTA && aptType != APTTYPE_NA)
{
DWORD idx;
(void)CoWaitForMultipleHandles(COWAIT_DEFAULT, INFINITE, 1, &state->waitEvent, &idx);
}
}
#endif
#endif
{
std::unique_lock<std::mutex> lock(state->waitMutex);
@ -610,7 +641,10 @@ STDAPI XAsyncGetStatus(
}
}
result = XAsyncGetStatus(asyncBlock, false);
{
AsyncBlockInternalGuard internal{ asyncBlock };
result = internal.GetStatus();
}
}
}
@ -673,16 +707,30 @@ STDAPI XAsyncRun(
__FUNCTION__,
[](XAsyncOp op, const XAsyncProviderData* data)
{
if (op == XAsyncOp::DoWork)
switch (op)
{
XAsyncWork* work = reinterpret_cast<XAsyncWork*>(data->context);
HRESULT hr = work(data->async);
XAsyncComplete(data->async, hr, 0);
case XAsyncOp::Begin:
return XAsyncSchedule(data->async, 0);
case XAsyncOp::DoWork:
{
XAsyncWork* work = reinterpret_cast<XAsyncWork*>(data->context);
HRESULT hr = work(data->async);
XAsyncComplete(data->async, hr, 0);
}
break;
case XAsyncOp::Cancel:
case XAsyncOp::Cleanup:
case XAsyncOp::GetResult:
break;
}
return S_OK;
}));
RETURN_HR(XAsyncSchedule(asyncBlock, 0));
return S_OK;
}
//
@ -718,7 +766,9 @@ STDAPI XAsyncBegin(
// We've successfully setup the call. Now kick off a
// Begin opcode. If this call fails, we use it to fail
// the async call, instead of failing XAsyncBegin.
// the async call, instead of failing XAsyncBegin. This is
// necessary to ensure that the async call state is properly
// cleaned up, both for us and for the user call.
HRESULT hr = provider(XAsyncOp::Begin, &state->providerData);
if (FAILED(hr))
@ -750,10 +800,21 @@ STDAPI XAsyncBeginAlloc(
_In_opt_ const char* identityName,
_In_ XAsyncProvider* provider,
_In_ size_t contextSize,
_Out_ void** context
_In_ size_t parameterBlockSize,
_In_opt_ void* parameterBlock
) noexcept
{
RETURN_HR_IF(E_INVALIDARG, contextSize == 0);
if (parameterBlockSize != 0)
{
RETURN_HR_IF(E_INVALIDARG, parameterBlock == nullptr || parameterBlockSize > contextSize);
}
else
{
RETURN_HR_IF(E_INVALIDARG, parameterBlock != nullptr);
}
RETURN_IF_FAILED(AllocState(asyncBlock, contextSize));
AsyncStateRef state;
@ -772,13 +833,20 @@ STDAPI XAsyncBeginAlloc(
ASSERT(state->providerData.context != nullptr);
memset(state->providerData.context, 0, contextSize);
*context = state->providerData.context;
if (parameterBlockSize != 0)
{
memcpy(state->providerData.context, parameterBlock, parameterBlockSize);
}
// We've successfully setup the call. Now kick off a
// Begin opcode. If this call fails, we use it to fail
// the async call, instead of failing XAsyncBegin.
// the async call, instead of failing XAsyncBegin. This is
// necessary to ensure that the async call state is properly
// cleaned up, both for us and for the user call.
HRESULT hr = provider(XAsyncOp::Begin, &state->providerData);
if (FAILED(hr))
{
XAsyncComplete(asyncBlock, hr, 0);
@ -865,7 +933,7 @@ STDAPI_(void) XAsyncComplete(
// clean up now. Also clean up if the call failed. The caller should
// have passed zero in here in that case but be tolerant for cases like
// sizeof().
if (requiredBufferSize == 0 || FAILED(result))
if ((requiredBufferSize == 0 || FAILED(result)) && completedNow)
{
// If we are going to cleanup steal the reference from the block.
doCleanup = true;
@ -886,7 +954,7 @@ STDAPI_(void) XAsyncComplete(
// Only signal / adjust needed buffer size if we were first to complete.
if (completedNow)
{
SignalCompletion(state);
FAIL_FAST_IF_FAILED(SignalCompletion(state));
}
// At this point asyncBlock may be unsafe to touch. As we've cleaned up

Просмотреть файл

@ -271,6 +271,9 @@ HRESULT TaskQueuePortImpl::Initialize(
m_terminationList.reset(new (std::nothrow) LocklessQueue<TerminationEntry*>(0));
RETURN_IF_NULL_ALLOC(m_terminationList);
m_pendingTerminationList.reset(new (std::nothrow) LocklessQueue<TerminationEntry*>(*m_terminationList.get()));
RETURN_IF_NULL_ALLOC(m_pendingTerminationList);
RETURN_IF_FAILED(m_timer.Initialize(this, [](void* context)
{
TaskQueuePortImpl* pthis = static_cast<TaskQueuePortImpl*>(context);
@ -509,9 +512,31 @@ void __stdcall TaskQueuePortImpl::Terminate(
_In_ void* token)
{
TerminationEntry* term = static_cast<TerminationEntry*>(token);
// Prevent anything else from coming into the queue
term->portContext->SetStatus(TaskQueuePortStatus::Terminated);
CancelPendingEntries(term->portContext, true);
// Are there existing suspends? AddSuspend returns
// true if this is the first suspend added.
if (term->portContext->AddSuspend())
{
ScheduleTermination(term);
}
else
{
m_pendingTerminationList->push_back(term, term->node);
term->node = 0;
}
// Balance our add
term->portContext->RemoveSuspend();
}
void __stdcall TaskQueuePortImpl::ScheduleTermination(
_In_ TerminationEntry* term)
{
// Insert the termination callback into the queue. Even if the
// main queue is empty, we still signal it and run through
// a cycle. This ensures we flush the queue out with no
@ -529,7 +554,6 @@ void __stdcall TaskQueuePortImpl::Terminate(
// We will not signal until we are marked as terminated. The queue could
// still be moving while we are running this terminate call.
term->portContext->SetStatus(TaskQueuePortStatus::Terminated);
SignalQueue();
// We must ensure we poke the queue threads in case there's
@ -683,6 +707,42 @@ bool __stdcall TaskQueuePortImpl::IsEmpty()
return empty;
}
HRESULT __stdcall TaskQueuePortImpl::SuspendTermination(
_In_ ITaskQueuePortContext* portContext
)
{
// This is necessary to ensure there is no race.
portContext->AddSuspend();
HRESULT hr = VerifyNotTerminated(portContext);
if (FAILED(hr))
{
portContext->RemoveSuspend();
RETURN_HR(hr);
}
return S_OK;
}
void __stdcall TaskQueuePortImpl::ResumeTermination(
_In_ ITaskQueuePortContext* portContext)
{
if (portContext->RemoveSuspend())
{
// Removed the last external callback. Look for
// parked terminations and reschedule them.
TerminationEntry *entry;
uint64_t address;
while (m_pendingTerminationList->pop_front(entry, address))
{
entry->node = address;
ScheduleTermination(entry);
}
}
}
HRESULT TaskQueuePortImpl::VerifyNotTerminated(
_In_ ITaskQueuePortContext* portContext)
{
@ -1160,6 +1220,34 @@ void __stdcall TaskQueuePortContextImpl::ItemQueued()
m_submitCallback->Invoke(m_type);
}
bool __stdcall TaskQueuePortContextImpl::AddSuspend()
{
return (m_suspendCount.fetch_add(1) == 0);
}
bool __stdcall TaskQueuePortContextImpl::RemoveSuspend()
{
for(;;)
{
uint32_t current = m_suspendCount.load();
// These should always be balanced and there is no
// valid case where this should happen, even
// for multiple therads racing.
if (current == 0)
{
ASSERT(false);
return true;
}
if (m_suspendCount.compare_exchange_weak(current, current -1))
{
return current == 1;
}
}
}
//
// TaskQueueImpl
//
@ -1613,7 +1701,8 @@ STDAPI XTaskQueueSubmitDelayedCallback(
referenced_ptr<ITaskQueuePortContext> portContext;
RETURN_IF_FAILED(aq->GetPortContext(port, portContext.address_of()));
RETURN_HR(portContext->GetPort()->QueueItem(portContext.get(), delayMs, callbackContext, callback));
RETURN_IF_FAILED(portContext->GetPort()->QueueItem(portContext.get(), delayMs, callbackContext, callback));
return S_OK;
}
//
@ -1691,7 +1780,8 @@ STDAPI XTaskQueueRegisterMonitor(
{
referenced_ptr<ITaskQueue> aq(GetQueue(queue));
RETURN_HR_IF(E_INVALIDARG, aq == nullptr);
RETURN_HR(aq->RegisterSubmitCallback(callbackContext, callback, token));
RETURN_IF_FAILED(aq->RegisterSubmitCallback(callbackContext, callback, token));
return S_OK;
}
//
@ -1795,3 +1885,45 @@ STDAPI_(void) XTaskQueueSetCurrentProcessTaskQueue(
XTaskQueueCloseHandle(previous);
}
}
//
// Submits a callback that will be invoked asynchronously via some external
// system. This is used to prevent queue termination while other work
// is happening.
//
STDAPI XTaskQueueSuspendTermination(
_In_ XTaskQueueHandle queue
) noexcept
{
referenced_ptr<ITaskQueue> aq(GetQueue(queue));
RETURN_HR_IF(E_INVALIDARG, aq == nullptr);
referenced_ptr<ITaskQueuePortContext> portContext;
RETURN_IF_FAILED(aq->GetPortContext(XTaskQueuePort::Work, portContext.address_of()));
RETURN_IF_FAILED(portContext->GetPort()->SuspendTermination(portContext.get()));
return S_OK;
}
//
// Tells the queue that a previously submitted external callback
// has been dispatched.
//
STDAPI_(void) XTaskQueueResumeTermination(
_In_ XTaskQueueHandle queue
) noexcept
{
referenced_ptr<ITaskQueue> aq(GetQueue(queue));
if (aq == nullptr)
{
return;
}
referenced_ptr<ITaskQueuePortContext> portContext;
if (FAILED(aq->GetPortContext(XTaskQueuePort::Work, portContext.address_of())))
{
return;
}
portContext->GetPort()->ResumeTermination(portContext.get());
}

Просмотреть файл

@ -202,6 +202,12 @@ public:
bool __stdcall IsEmpty();
HRESULT __stdcall SuspendTermination(
_In_ ITaskQueuePortContext* portContext);
void __stdcall ResumeTermination(
_In_ ITaskQueuePortContext* portContext);
private:
struct WaitRegistration;
@ -246,6 +252,7 @@ private:
std::unique_ptr<LocklessQueue<QueueEntry>> m_queueList;
std::unique_ptr<LocklessQueue<QueueEntry>> m_pendingList;
std::unique_ptr<LocklessQueue<TerminationEntry*>> m_terminationList;
std::unique_ptr<LocklessQueue<TerminationEntry*>> m_pendingTerminationList;
OS::WaitTimer m_timer;
OS::ThreadPool m_threadPool;
std::atomic<uint64_t> m_timerDue = { UINT64_MAX };
@ -285,6 +292,7 @@ private:
void SubmitPendingCallback();
void SignalTerminations();
void ScheduleTermination(_In_ TerminationEntry* term);
void SignalQueue();
@ -339,6 +347,9 @@ public:
void __stdcall ItemQueued() override;
bool __stdcall AddSuspend() override;
bool __stdcall RemoveSuspend() override;
referenced_ptr<ITaskQueuePort> Port;
referenced_ptr<ITaskQueue> Source;
@ -348,6 +359,7 @@ private:
XTaskQueuePort m_type = XTaskQueuePort::Work;
SubmitCallback* m_submitCallback = nullptr;
std::atomic<TaskQueuePortStatus> m_status = { TaskQueuePortStatus::Active };
std::atomic<uint32_t> m_suspendCount = { 0 };
};
class TaskQueueImpl : public Api<ApiId::TaskQueue, ITaskQueue>

Просмотреть файл

@ -67,12 +67,18 @@ struct ITaskQueuePort: IApi
_In_ ITaskQueuePortContext* portContext) = 0;
virtual bool __stdcall DrainOneItem() = 0;
virtual bool __stdcall Wait(
_In_ ITaskQueuePortContext* portContext,
_In_ uint32_t timeout) = 0;
virtual bool __stdcall IsEmpty() = 0;
virtual HRESULT __stdcall SuspendTermination(
_In_ ITaskQueuePortContext* portContext) = 0;
virtual void __stdcall ResumeTermination(
_In_ ITaskQueuePortContext* portContext) = 0;
};
// The status of a port on the queue.
@ -102,6 +108,9 @@ struct ITaskQueuePortContext : IApi
_In_ TaskQueuePortStatus status) = 0;
virtual void __stdcall ItemQueued() = 0;
virtual bool __stdcall AddSuspend() = 0;
virtual bool __stdcall RemoveSuspend() = 0;
};
// The task queue. The public flat API is built entirely on

Просмотреть файл

@ -0,0 +1,39 @@
// Copyright(c) Microsoft Corporation. All rights reserved.
//
// These APIs should be reserved for driving unit test harnesses.
#pragma once
#include "XAsyncProvider.h"
/// <summary>
/// Initializes an async block for use. Once begun calls such
/// as XAsyncGetStatus will provide meaningful data. It is assumed the
/// async work will begin on some system defined thread after this call
/// returns. The token and function parameters can be used to help identify
/// mismatched Begin/GetResult calls. The token is typically the function
/// pointer of the async API you are implementing, and the functionName parameter
/// is typically the __FUNCTION__ compiler macro.
///
/// This variant of XAsyncBegin will allocate additional memory of size contextSize
/// and use this as the context pointer for async provider callbacks. The memory
/// pointer is returned in 'context'. The lifetime of this memory is managed
/// by the async library and will be freed automatically when the call
/// completes.
/// </summary>
/// <param name='asyncBlock'>A pointer to the XAsyncBlock that holds data for the call.</param>
/// <param name='identity'>An optional arbitrary pointer that can be used to identify this call.</param>
/// <param name='identityName'>An optional string that names the async call. This is typically the __FUNCTION__ compiler macro.</param>
/// <param name='provider'>The function callback to invoke to implement the async call.</param>
/// <param name='contextSize'>The size, in bytes, of additional context memory to allocate.</param>
/// <param name='parameterBlockSize'>The size of a parameter block to copy into the allocated context.</param>
/// <param name='parameterBlock'>The parameter block to copy. This will be copied into the allocated context.</param>
STDAPI XAsyncBeginAlloc(
_Inout_ XAsyncBlock* asyncBlock,
_In_opt_ const void* identity,
_In_opt_ const char* identityName,
_In_ XAsyncProvider* provider,
_In_ size_t contextSize,
_In_ size_t parameterBlockSize,
_In_opt_ void* parameterBlock
) noexcept;

Просмотреть файл

@ -14,4 +14,23 @@
/// <param name='port'>The port to check.</param>
STDAPI_(bool) XTaskQueueIsEmpty(
_In_ XTaskQueueHandle queue,
_In_ XTaskQueuePort port);
_In_ XTaskQueuePort port
) noexcept;
/// <summary>
/// Suspends terminations on the task queue. May return an error if
/// the queue is already terminated.
/// </summary>
/// <param name='queue'>The queue to suspend terminations.</param>
STDAPI XTaskQueueSuspendTermination(
_In_ XTaskQueueHandle queue
) noexcept;
/// <summary>
/// Resumes the ability to terminate the task queue. If a termination was
/// attempted it will be continued.
/// </summary>
/// <param name='queue'>The queue resume terminations.</param>
STDAPI_(void) XTaskQueueResumeTermination(
_In_ XTaskQueueHandle queue
) noexcept;

Просмотреть файл

@ -4,6 +4,7 @@
#include "UnitTestIncludes.h"
#include "XAsync.h"
#include "XAsyncProvider.h"
#include "XAsyncProviderPriv.h"
#include "XTaskQueue.h"
#include "XTaskQueuePriv.h"
@ -71,7 +72,7 @@ DEFINE_TEST_CLASS(AsyncBlockTests)
private:
XTaskQueueHandle queue = nullptr;
struct FactorialCallData
{
DWORD value = 0;
@ -219,6 +220,32 @@ private:
return S_OK;
}
static HRESULT CALLBACK FactorialWorkerDistributedWithSchedule(XAsyncOp opCode, const XAsyncProviderData* data)
{
if (opCode == XAsyncOp::Begin)
{
FactorialCallData* d = (FactorialCallData*)data->context;
// leak a ref on this guy so we don't try to free it. We need
// to do two addrefs because a new object starts with refcount
// of zero. The factorial async process will addref/release so
// we need two to "leak" it (not really leaked; the memory is
// owned by the async logic)
d->AddRef();
d->AddRef();
}
HRESULT hr = FactorialWorkerDistributed(opCode, data);
if (SUCCEEDED(hr) && opCode == XAsyncOp::Begin)
{
hr = XAsyncSchedule(data->async, 0);
}
return hr;
}
static HRESULT FactorialAsync(FactorialCallData* data, XAsyncBlock* async)
{
HRESULT hr = XAsyncBegin(async, data, FactorialAsync, __FUNCTION__, FactorialWorkerSimple);
@ -241,23 +268,7 @@ private:
static HRESULT FactorialAllocateAsync(DWORD value, XAsyncBlock* async)
{
void* context;
HRESULT hr = XAsyncBeginAlloc(async, FactorialAsync, __FUNCTION__, FactorialWorkerDistributed, sizeof(FactorialCallData), &context);
if (SUCCEEDED(hr))
{
FactorialCallData* data = new (context) FactorialCallData;
data->value = value;
// leak a ref on this guy so we don't try to free it. We need
// to do two addrefs because a new object starts with refcount
// of zero. The factorial async process will addref/release so
// we need two to "leak" it (not really leaked; the memory is
// owned by the async logic)
data->AddRef();
data->AddRef();
hr = XAsyncSchedule(async, 0);
}
HRESULT hr = XAsyncBeginAlloc(async, FactorialAsync, __FUNCTION__, FactorialWorkerDistributedWithSchedule, sizeof(FactorialCallData), sizeof(DWORD), &value);
return hr;
}
@ -342,6 +353,7 @@ public:
AsyncBlockTests::~AsyncBlockTests()
{
VERIFY_ARE_EQUAL(s_AsyncLibGlobalStateCount, (DWORD)0);
XTaskQueueTerminate(queue, true, nullptr, nullptr);
XTaskQueueCloseHandle(queue);
}
@ -987,4 +999,58 @@ public:
VERIFY_SUCCEEDED(XAsyncGetStatus(&async, true));
VERIFY_ARE_EQUAL((DWORD)WAIT_OBJECT_0, WaitForSingleObject(context.evt, 2500));
}
DEFINE_TEST_CASE(VerifyBeginAfterTerminate)
{
XAsyncBlock async{};
VERIFY_SUCCEEDED(XTaskQueueCreate(XTaskQueueDispatchMode::ThreadPool, XTaskQueueDispatchMode::ThreadPool, &async.queue));
auto provider = [](XAsyncOp, const XAsyncProviderData*)
{
return S_OK;
};
// Terminate the queue
XTaskQueueTerminate(async.queue, true, nullptr, nullptr);
// XAsyncBegin should fail early with an abort.
VERIFY_ARE_EQUAL(E_ABORT, XAsyncBegin(&async, nullptr, nullptr, nullptr, provider));
XTaskQueueCloseHandle(async.queue);
}
DEFINE_TEST_CASE(VerifyFailureInDoWork)
{
XAsyncBlock async{};
VERIFY_SUCCEEDED(XTaskQueueCreate(XTaskQueueDispatchMode::ThreadPool, XTaskQueueDispatchMode::ThreadPool, &async.queue));
constexpr static HRESULT hrSpecial = 0x8009ABCD;
auto provider = [](XAsyncOp op, const XAsyncProviderData* data)
{
switch(op)
{
case XAsyncOp::Begin:
return XAsyncSchedule(data->async, 0);
case XAsyncOp::Cleanup:
break;
case XAsyncOp::DoWork:
return hrSpecial;
default:
VERIFY_FAIL();
break;
}
return S_OK;
};
// Ensure that the call runs through and correctly reports our special
// error.
VERIFY_SUCCEEDED(XAsyncBegin(&async, nullptr, nullptr, nullptr, provider));
VERIFY_ARE_EQUAL(hrSpecial, XAsyncGetStatus(&async, true));
XTaskQueueCloseHandle(async.queue);
}
};

Просмотреть файл

@ -110,6 +110,11 @@ public:
TEST_CLASS_CLEANUP(ClassCleanup)
{
//
// Note: this is a global refcount for tracking
// leaks in the task queue. If any other tests fail
// this may also fail, as those tests could have leaked.
//
uint32_t gr = ApiDiag::g_globalApiRefs;
VERIFY_ARE_EQUAL(0u, gr);
return true;
@ -1184,4 +1189,28 @@ public:
NextStep(&step, 7, L"Closing outer queue");
XTaskQueueCloseHandle(outer.Release());
}
DEFINE_TEST_CASE(VerifyTerminateWaitsForSuspends)
{
AutoQueueHandle queue;
VERIFY_SUCCEEDED(XTaskQueueCreate(XTaskQueueDispatchMode::ThreadPool, XTaskQueueDispatchMode::ThreadPool, &queue));
AutoHandle waitHandle = CreateEvent(nullptr, TRUE, FALSE, nullptr);
VERIFY_IS_NOT_NULL(waitHandle);
auto terminatedCallback = [](void* context)
{
HANDLE h = (HANDLE)context;
SetEvent(h);
};
VERIFY_SUCCEEDED(XTaskQueueSuspendTermination(queue));
VERIFY_SUCCEEDED(XTaskQueueTerminate(queue, false, waitHandle.Handle(), terminatedCallback));
VERIFY_ARE_EQUAL((DWORD)WAIT_TIMEOUT, WaitForSingleObject(waitHandle, 2000));
XTaskQueueResumeTermination(queue);
VERIFY_ARE_EQUAL((DWORD)WAIT_OBJECT_0, WaitForSingleObject(waitHandle, 2000));
}
};

Просмотреть файл

@ -107,6 +107,7 @@ set(Task_Source_Files
../../../Source/Task/ThreadPool.h
../../../Source/Task/WaitTimer.h
../../../Source/Task/XTaskQueuePriv.h
../../../Source/Task/XAsyncProviderPriv.h
)
set(Task_Windows_Source_Files