Expose async cleanup (#541)
The current blocking version of HCCleanup has 3 major flaws: - It always uses the system task queue, which may be undesirable by some clients - It blocks waiting for the internal work to complete, which could cause a deadlock - It does not expose a result so in the case of multiple libHttpClient initializations it is impossible to tell if the memory hooks are safe to remove This change simply exposes the internal asynchronous cleanup functionality allowing the caller control to bypass all these issues
This commit is contained in:
Родитель
0541869696
Коммит
1eb312c47f
|
@ -136,9 +136,19 @@ STDAPI HCInitialize(_In_opt_ HCInitArgs* args) noexcept;
|
|||
/// Immediately reclaims all resources associated with the library.
|
||||
/// If you called HCMemSetFunctions(), call this before shutting down your app's memory manager.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Deprecated, Use HCCleanupAsync instead which allows control of which queue is running the cleanup work and does not potentially deadlock.
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
STDAPI_(void) HCCleanup() noexcept;
|
||||
|
||||
/// <summary>
|
||||
/// Reclaims all resources associated with the library.
|
||||
/// If you called HCMemSetFunctions(), call this before shutting down your app's memory manager.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
STDAPI HCCleanupAsync(XAsyncBlock* async) noexcept;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the version of the library
|
||||
/// </summary>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "../HTTP/httpcall.h"
|
||||
#include "buildver.h"
|
||||
#include "global.h"
|
||||
#include "../Logger/trace_internal.h"
|
||||
#include "../Mock/lhc_mock.h"
|
||||
|
||||
#if !HC_NOWEBSOCKETS
|
||||
|
@ -33,6 +34,8 @@ HRESULT http_singleton::singleton_access(
|
|||
// Create the singleton only for the first client calling create
|
||||
if (!s_useCount)
|
||||
{
|
||||
HCTraceImplInit();
|
||||
|
||||
PerformEnv performEnv;
|
||||
RETURN_IF_FAILED(Internal_InitializeHttpPlatform(createArgs, performEnv));
|
||||
|
||||
|
@ -113,7 +116,38 @@ HRESULT http_singleton::cleanup_async(
|
|||
) noexcept
|
||||
{
|
||||
std::shared_ptr<http_singleton> singleton{};
|
||||
RETURN_IF_FAILED(singleton_access(singleton_access_mode::cleanup, nullptr, singleton));
|
||||
HRESULT hr = singleton_access(singleton_access_mode::cleanup, nullptr, singleton);
|
||||
|
||||
// if the singleton is still in use, or already cleaned up, fail immediately
|
||||
if (FAILED(hr))
|
||||
{
|
||||
intptr_t hrPtrSize = hr;
|
||||
return XAsyncBegin(
|
||||
async,
|
||||
reinterpret_cast<void*>(hrPtrSize),
|
||||
reinterpret_cast<void*>(cleanup_async),
|
||||
__FUNCTION__,
|
||||
[](XAsyncOp op, const XAsyncProviderData* data)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case XAsyncOp::Begin:
|
||||
{
|
||||
intptr_t hrPtrSize = reinterpret_cast<intptr_t>(data->context);
|
||||
return static_cast<HRESULT>(hrPtrSize);
|
||||
}
|
||||
case XAsyncOp::Cleanup:
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
default:
|
||||
{
|
||||
assert(false);
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return XAsyncBegin(
|
||||
async,
|
||||
|
@ -147,6 +181,9 @@ HRESULT http_singleton::cleanup_async(
|
|||
// self is the only reference at this point, the singleton will be destroyed on this thread.
|
||||
self.reset();
|
||||
|
||||
// cleanup tracing now that we are done
|
||||
HCTraceImplCleanup();
|
||||
|
||||
XAsyncComplete(data->async, S_OK, 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "../HTTP/httpcall.h"
|
||||
#include "buildver.h"
|
||||
#include "global.h"
|
||||
#include "../Logger/trace_internal.h"
|
||||
|
||||
using namespace xbox::httpclient;
|
||||
|
||||
|
@ -27,7 +26,6 @@ STDAPI
|
|||
HCInitialize(_In_opt_ HCInitArgs* args) noexcept
|
||||
try
|
||||
{
|
||||
HCTraceImplInit();
|
||||
return http_singleton::create(args);
|
||||
}
|
||||
CATCH_RETURN()
|
||||
|
@ -36,16 +34,21 @@ STDAPI_(void) HCCleanup() noexcept
|
|||
try
|
||||
{
|
||||
XAsyncBlock async{};
|
||||
HRESULT hr = http_singleton::cleanup_async(&async);
|
||||
HRESULT hr = HCCleanupAsync(&async);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
XAsyncGetStatus(&async, true);
|
||||
}
|
||||
|
||||
HCTraceImplCleanup();
|
||||
}
|
||||
CATCH_RETURN_WITH(;)
|
||||
|
||||
STDAPI HCCleanupAsync(XAsyncBlock* async) noexcept
|
||||
try
|
||||
{
|
||||
return http_singleton::cleanup_async(async);
|
||||
}
|
||||
CATCH_RETURN()
|
||||
|
||||
STDAPI
|
||||
HCSetGlobalProxy(_In_ const char* proxyUri) noexcept
|
||||
try
|
||||
|
|
Загрузка…
Ссылка в новой задаче