196 строки
8.7 KiB
C
196 строки
8.7 KiB
C
// Copyright (c) Microsoft Corporation
|
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
|
|
#if !defined(__cplusplus)
|
|
#error C++11 required
|
|
#endif
|
|
|
|
#pragma once
|
|
#include "XAsync.h"
|
|
|
|
extern "C"
|
|
{
|
|
|
|
enum class XAsyncOp : uint32_t
|
|
{
|
|
/// <summary>
|
|
/// An async provider is invoked with this opcode during XAsyncBegin or XAsyncBeginAlloc.
|
|
/// If the provider implements this op code, they should start their asynchronous task,
|
|
/// either by calling XAsyncSchedule or through exterior means. This callback is
|
|
/// called synchronously in the XAsyncBegin call chain, so it should never block.
|
|
/// </summary>
|
|
Begin,
|
|
|
|
/// <summary>
|
|
/// An async provider is invoked with this opcode when XAsyncSchedule has been called to
|
|
/// schedule work. Implementations should perform their asynchronous work and then call
|
|
/// XAsyncComplete with the data payload size. If additional work needs to be done they
|
|
/// can schedule it and return E_PENDING.
|
|
/// </summary>
|
|
DoWork,
|
|
|
|
/// <summary>
|
|
/// An async provider is invoked with this opcode after an async call completes and the
|
|
/// user needs to get the resulting data payload. The buffer and bufferSize have
|
|
/// been arg checked.
|
|
/// </summary>
|
|
GetResult,
|
|
|
|
/// <summary>
|
|
/// An async provider is invoked with this opcode when the async work should be canceled. If
|
|
/// you can cancel your work you should call XAsyncComplete with an error code of E_ABORT when
|
|
/// the work has been canceled.
|
|
/// </summary>
|
|
Cancel,
|
|
|
|
/// <summary>
|
|
/// An async provider is invoked with this opcode when the async call is over and
|
|
/// data in the context can be cleaned up.
|
|
/// </summary>
|
|
Cleanup
|
|
};
|
|
|
|
/// <summary>
|
|
/// A data block passed to an async provider callback. Fields in this structure are filled
|
|
/// in as the call progresses.
|
|
/// </summary>
|
|
struct XAsyncProviderData
|
|
{
|
|
/// <summary>
|
|
/// The async block for the call.
|
|
/// </summary>
|
|
XAsyncBlock* async;
|
|
|
|
/// <summary>
|
|
/// Valid during a GetResult opcode and holds the size of the buffer. This will
|
|
/// be at least as large as the data size provided to XAsyncComplete.
|
|
/// </summary>
|
|
size_t bufferSize;
|
|
|
|
/// <summary>
|
|
/// Valid during a GetResult opcode and holds the output data buffer.
|
|
/// </summary>
|
|
void* buffer;
|
|
|
|
/// <summary>
|
|
/// Valid during any opcode this is a user provided context pointer that was provided
|
|
/// to XAsyncBegin. It should be freed during the Cleanup opcode.
|
|
/// </summary>
|
|
void* context;
|
|
};
|
|
|
|
/// <summary>
|
|
/// A callback function that implements the async call. This function will be invoked
|
|
/// multiple times with different XAsyncOp operation codes to indicate what work it
|
|
/// should perform.
|
|
/// </summary>
|
|
/// <param name='op'>The async operatiopn to perform.</param>
|
|
/// <param name='data'>Data used to track the async call.</param>
|
|
/// <seealso cref='XAsyncProviderData' />
|
|
typedef HRESULT CALLBACK XAsyncProvider(_In_ XAsyncOp op, _Inout_ const XAsyncProviderData* data);
|
|
|
|
/// <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.
|
|
/// </summary>
|
|
/// <param name='asyncBlock'>A pointer to the XAsyncBlock that holds data for the call.</param>
|
|
/// <param name='context'>An optional context pointer that will be stored in the XAsyncProviderData object passed back to the XAsyncProvider callback.</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>
|
|
STDAPI XAsyncBegin(
|
|
_Inout_ XAsyncBlock* asyncBlock,
|
|
_In_opt_ void* context,
|
|
_In_opt_ const void* identity,
|
|
_In_opt_ const char* identityName,
|
|
_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
|
|
/// work. If work should be scheduled after a delay, pass the number of ms XAsyncSchedule should wait
|
|
/// before it schedules work.
|
|
/// </summary>
|
|
/// <param name='asyncBlock'>A pointer to the XAsyncBlock that was passed to XAsyncBegin.</param>
|
|
/// <param name='delayInMs'>How long the system should wait before scheduling the async call with the async queue.</param>
|
|
STDAPI XAsyncSchedule(
|
|
_Inout_ XAsyncBlock* asyncBlock,
|
|
_In_ uint32_t delayInMs
|
|
) noexcept;
|
|
|
|
/// <summary>
|
|
/// Called when async work is completed and the results can be returned.
|
|
/// The caller should supply the resulting data payload size. If the call
|
|
/// has no data payload, pass zero.
|
|
/// </summary>
|
|
/// <param name='asyncBlock'>A pointer to the XAsyncBlock that was passed to XAsyncBegin.</param>
|
|
/// <param name='result'>The resut of the call. This should not be E_PENDING as that result is reserved for an incomplete call. If you are canceling this call you should pass E_ABORT.</param>
|
|
/// <param name='requiredBufferSize'>The required size in bytes of the call result. If the call has no data to return this should be zero.</param>
|
|
STDAPI_(void) XAsyncComplete(
|
|
_Inout_ XAsyncBlock* asyncBlock,
|
|
_In_ HRESULT result,
|
|
_In_ size_t requiredBufferSize
|
|
) noexcept;
|
|
|
|
/// <summary>
|
|
/// Returns the result data for the asynchronous operation. After this call
|
|
/// the async block is completed and no longer associated with the
|
|
/// operation. The token parameter should match the token passed into
|
|
/// XAsyncBegin.
|
|
/// </summary>
|
|
/// <param name='asyncBlock'>A pointer to the XAsyncBlock that was passed to XAsyncBegin.</param>
|
|
/// <param name='identity'>An optional pointer used to match this result call with a prior XAsyncBegin call. If an identity pointer was passed to XAsyncBegin, the same pointer must be passed here.</param>
|
|
/// <param name='bufferSize'>The size of the provided buffer, in bytes.</param>
|
|
/// <param name='buffer'>A pointer to the result buffer.</param>
|
|
/// <param name='bufferUsed'>An optional pointer that contains the number of bytes written to the buffer. This is defined as the requiredResultSize passed to XAsyncComplete.</param>
|
|
STDAPI XAsyncGetResult(
|
|
_Inout_ XAsyncBlock* asyncBlock,
|
|
_In_opt_ const void* identity,
|
|
_In_ size_t bufferSize,
|
|
_Out_writes_bytes_to_opt_(bufferSize, *bufferUsed) void* buffer,
|
|
_Out_opt_ size_t* bufferUsed
|
|
) noexcept;
|
|
|
|
/// <summary>
|
|
/// This is used generate an identity to pass to XAsyncBegin/XAsyncGetResult
|
|
/// </summary>
|
|
#define XASYNC_IDENTITY(method) #method
|
|
|
|
} // extern "C"
|