[PATCH 4/6] windows.media.speech: Implement handler for IAsyncOperation.
Rémi Bernon
rbernon at codeweavers.com
Fri Apr 1 04:23:52 CDT 2022
On 4/1/22 11:15, Rémi Bernon wrote:
> On 3/31/22 18:17, Bernhard Kölbl wrote:
>> Signed-off-by: Bernhard Kölbl <besentv at gmail.com>
>> ---
>> dlls/windows.media.speech/async.c | 40 ++++++++++++++++++++----
>> dlls/windows.media.speech/private.h | 1 +
>> dlls/windows.media.speech/recognizer.c | 10 +++++-
>> dlls/windows.media.speech/tests/speech.c | 25 +++++++--------
>> 4 files changed, 55 insertions(+), 21 deletions(-)
>>
>> diff --git a/dlls/windows.media.speech/async.c
>> b/dlls/windows.media.speech/async.c
>> index 5b74ec60be1..767b4a3a4e4 100644
>> --- a/dlls/windows.media.speech/async.c
>> +++ b/dlls/windows.media.speech/async.c
>> @@ -35,6 +35,10 @@ struct async_operation
>> IAsyncInfo IAsyncInfo_iface;
>> const GUID *iid;
>> LONG ref;
>> +
>> + IAsyncOperationCompletedHandler_IInspectable *handler;
>> + BOOLEAN handler_set;
>> + AsyncStatus status;
>> };
>> static inline struct async_operation
>> *impl_from_IAsyncOperation_IInspectable(IAsyncOperation_IInspectable
>> *iface)
>> @@ -110,15 +114,26 @@ static HRESULT WINAPI
>> async_operation_GetTrustLevel( IAsyncOperation_IInspectabl
>> static HRESULT WINAPI async_operation_put_Completed(
>> IAsyncOperation_IInspectable *iface,
>>
>> IAsyncOperationCompletedHandler_IInspectable *handler )
>> {
>> - FIXME("iface %p, handler %p stub!\n", iface, handler);
>> - return E_NOTIMPL;
>> + struct async_operation *impl =
>> impl_from_IAsyncOperation_IInspectable(iface);
>> +
>> + TRACE("iface %p, handler %p.\n", iface, handler);
>> +
>> + if (impl->handler_set) return E_ILLEGAL_DELEGATE_ASSIGNMENT;
>> + impl->handler = handler;
>> + impl->handler_set = TRUE;
>> +
>> + if (impl->status == Completed)
>> + return async_operation_notify(iface);
>> +
>> + return S_OK;
>> }
>> static HRESULT WINAPI async_operation_get_Completed(
>> IAsyncOperation_IInspectable *iface,
>>
>> IAsyncOperationCompletedHandler_IInspectable **handler )
>> {
>> - FIXME("iface %p, handler %p stub!\n", iface, handler);
>> - return E_NOTIMPL;
>> + FIXME("iface %p, handler %p semi stub!\n", iface, handler);
>> + *handler = NULL;
>> + return S_OK;
>> }
>> static HRESULT WINAPI async_operation_GetResults(
>> IAsyncOperation_IInspectable *iface, IInspectable ***results )
>> @@ -159,8 +174,10 @@ static HRESULT WINAPI
>> async_operation_info_get_Id( IAsyncInfo *iface, UINT32 *id
>> static HRESULT WINAPI async_operation_info_get_Status( IAsyncInfo
>> *iface, AsyncStatus *status )
>> {
>> - FIXME("iface %p, status %p stub!\n", iface, status);
>> - return E_NOTIMPL;
>> + struct async_operation *impl = impl_from_IAsyncInfo(iface);
>> + TRACE("iface %p, status %p.\n", iface, status);
>> + *status = impl->status;
>> + return S_OK;
>> }
>> static HRESULT WINAPI async_operation_info_get_ErrorCode( IAsyncInfo
>> *iface, HRESULT *error_code )
>> @@ -218,3 +235,14 @@ HRESULT async_operation_create( const GUID *iid,
>> IAsyncOperation_IInspectable **
>> TRACE("created %p\n", *out);
>> return S_OK;
>> }
>> +
>> +HRESULT async_operation_notify( IAsyncOperation_IInspectable
>> *operation )
>> +{
>> + struct async_operation *impl =
>> impl_from_IAsyncOperation_IInspectable(operation);
>> +
>> + impl->status = Completed;
>> + if (impl->handler)
>> +
>> IAsyncOperationCompletedHandler_IInspectable_Invoke(impl->handler,
>> operation, impl->status);
>> +
>> + return S_OK;
>> +}
>> \ No newline at end of file
>
> It might require a bit of reorganization of the patches, to introduce
> the result first, but I think you only need one private helper overall,
> which would be something like "async_operation_complete". I don't think
> it makes much sense to have two separate "set_result" + "notify"
> operations.
>
> It would also be interesting to add tests for the IAsyncInfo and results
> before setting a completion handler. As far as I can tell, the async is
> actually completed by the put_Completed call, not right when it is
> created. This would make the "already completed" case in put_Completed
> go away.
>
> Imho adding the tests first, in a separate patch, including with the
> results tests also would make things a bit more clear in term of to
> which direction the implementation should go.
>
And I'm guessing here, but I think that truly async operations could
work with a "async_operation_start", also called from put_Completed,
starting a task on a worker thread at that point to also avoid the
situation where the task completes before the handler has been provided.
FWIW instead (or in addition to an async_operation_complete) you could
already introduce a "async_operation_start" helper, which would later be
able to either queue long tasks to worker thread, or simply execute and
complete short async tasks synchronously.
--
Rémi Bernon <rbernon at codeweavers.com>
More information about the wine-devel
mailing list