Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
0f25fadb
Commit
0f25fadb
authored
Sep 18, 2022
by
Nikolay Sivov
Committed by
Alexandre Julliard
Sep 20, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
threadpoolwinrt: Add initial implementation of RunAsync.
Signed-off-by:
Nikolay Sivov
<
nsivov@codeweavers.com
>
parent
511be2e8
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
684 additions
and
6 deletions
+684
-6
configure
configure
+1
-0
configure.ac
configure.ac
+1
-0
main.c
dlls/threadpoolwinrt/main.c
+385
-6
Makefile.in
dlls/threadpoolwinrt/tests/Makefile.in
+5
-0
threadpool.c
dlls/threadpoolwinrt/tests/threadpool.c
+292
-0
No files found.
configure
View file @
0f25fadb
...
@@ -21960,6 +21960,7 @@ wine_fn_config_makefile dlls/tbs enable_tbs
...
@@ -21960,6 +21960,7 @@ wine_fn_config_makefile dlls/tbs enable_tbs
wine_fn_config_makefile dlls/tdh enable_tdh
wine_fn_config_makefile dlls/tdh enable_tdh
wine_fn_config_makefile dlls/tdi.sys enable_tdi_sys
wine_fn_config_makefile dlls/tdi.sys enable_tdi_sys
wine_fn_config_makefile dlls/threadpoolwinrt enable_threadpoolwinrt
wine_fn_config_makefile dlls/threadpoolwinrt enable_threadpoolwinrt
wine_fn_config_makefile dlls/threadpoolwinrt/tests enable_tests
wine_fn_config_makefile dlls/toolhelp.dll16 enable_win16
wine_fn_config_makefile dlls/toolhelp.dll16 enable_win16
wine_fn_config_makefile dlls/traffic enable_traffic
wine_fn_config_makefile dlls/traffic enable_traffic
wine_fn_config_makefile dlls/twain.dll16 enable_win16
wine_fn_config_makefile dlls/twain.dll16 enable_win16
...
...
configure.ac
View file @
0f25fadb
...
@@ -3065,6 +3065,7 @@ WINE_CONFIG_MAKEFILE(dlls/tbs)
...
@@ -3065,6 +3065,7 @@ WINE_CONFIG_MAKEFILE(dlls/tbs)
WINE_CONFIG_MAKEFILE(dlls/tdh)
WINE_CONFIG_MAKEFILE(dlls/tdh)
WINE_CONFIG_MAKEFILE(dlls/tdi.sys)
WINE_CONFIG_MAKEFILE(dlls/tdi.sys)
WINE_CONFIG_MAKEFILE(dlls/threadpoolwinrt)
WINE_CONFIG_MAKEFILE(dlls/threadpoolwinrt)
WINE_CONFIG_MAKEFILE(dlls/threadpoolwinrt/tests)
WINE_CONFIG_MAKEFILE(dlls/toolhelp.dll16,enable_win16)
WINE_CONFIG_MAKEFILE(dlls/toolhelp.dll16,enable_win16)
WINE_CONFIG_MAKEFILE(dlls/traffic)
WINE_CONFIG_MAKEFILE(dlls/traffic)
WINE_CONFIG_MAKEFILE(dlls/twain.dll16,enable_win16)
WINE_CONFIG_MAKEFILE(dlls/twain.dll16,enable_win16)
...
...
dlls/threadpoolwinrt/main.c
View file @
0f25fadb
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
*/
*/
#include <stdarg.h>
#include <stdarg.h>
#include <assert.h>
#define COBJMACROS
#define COBJMACROS
#include "windef.h"
#include "windef.h"
...
@@ -52,6 +53,13 @@ struct threadpool_factory
...
@@ -52,6 +53,13 @@ struct threadpool_factory
LONG
refcount
;
LONG
refcount
;
};
};
struct
async_action
{
IAsyncAction
IAsyncAction_iface
;
IAsyncInfo
IAsyncInfo_iface
;
LONG
refcount
;
};
static
inline
struct
threadpool_factory
*
impl_from_IActivationFactory
(
IActivationFactory
*
iface
)
static
inline
struct
threadpool_factory
*
impl_from_IActivationFactory
(
IActivationFactory
*
iface
)
{
{
return
CONTAINING_RECORD
(
iface
,
struct
threadpool_factory
,
IActivationFactory_iface
);
return
CONTAINING_RECORD
(
iface
,
struct
threadpool_factory
,
IActivationFactory_iface
);
...
@@ -62,6 +70,374 @@ static inline struct threadpool_factory *impl_from_IThreadPoolStatics(IThreadPoo
...
@@ -62,6 +70,374 @@ static inline struct threadpool_factory *impl_from_IThreadPoolStatics(IThreadPoo
return
CONTAINING_RECORD
(
iface
,
struct
threadpool_factory
,
IThreadPoolStatics_iface
);
return
CONTAINING_RECORD
(
iface
,
struct
threadpool_factory
,
IThreadPoolStatics_iface
);
}
}
static
inline
struct
async_action
*
impl_from_IAsyncAction
(
IAsyncAction
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
async_action
,
IAsyncAction_iface
);
}
static
inline
struct
async_action
*
impl_from_IAsyncInfo
(
IAsyncInfo
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
async_action
,
IAsyncInfo_iface
);
}
static
HRESULT
STDMETHODCALLTYPE
async_action_QueryInterface
(
IAsyncAction
*
iface
,
REFIID
iid
,
void
**
out
)
{
struct
async_action
*
action
=
impl_from_IAsyncAction
(
iface
);
TRACE
(
"iface %p, iid %s, out %p.
\n
"
,
iface
,
debugstr_guid
(
iid
),
out
);
if
(
IsEqualIID
(
iid
,
&
IID_IAsyncAction
)
||
IsEqualIID
(
iid
,
&
IID_IInspectable
)
||
IsEqualIID
(
iid
,
&
IID_IUnknown
))
{
*
out
=
iface
;
}
else
if
(
IsEqualIID
(
iid
,
&
IID_IAsyncInfo
))
{
*
out
=
&
action
->
IAsyncInfo_iface
;
}
else
{
*
out
=
NULL
;
WARN
(
"Unsupported interface %s.
\n
"
,
debugstr_guid
(
iid
));
}
IUnknown_AddRef
((
IUnknown
*
)
*
out
);
return
S_OK
;
}
static
ULONG
STDMETHODCALLTYPE
async_action_AddRef
(
IAsyncAction
*
iface
)
{
struct
async_action
*
action
=
impl_from_IAsyncAction
(
iface
);
ULONG
refcount
=
InterlockedIncrement
(
&
action
->
refcount
);
TRACE
(
"iface %p, refcount %lu.
\n
"
,
iface
,
refcount
);
return
refcount
;
}
static
ULONG
STDMETHODCALLTYPE
async_action_Release
(
IAsyncAction
*
iface
)
{
struct
async_action
*
action
=
impl_from_IAsyncAction
(
iface
);
ULONG
refcount
=
InterlockedDecrement
(
&
action
->
refcount
);
TRACE
(
"iface %p, refcount %lu.
\n
"
,
iface
,
refcount
);
if
(
!
refcount
)
free
(
action
);
return
refcount
;
}
static
HRESULT
STDMETHODCALLTYPE
async_action_GetIids
(
IAsyncAction
*
iface
,
ULONG
*
iid_count
,
IID
**
iids
)
{
FIXME
(
"iface %p, iid_count %p, iids %p stub!
\n
"
,
iface
,
iid_count
,
iids
);
return
E_NOTIMPL
;
}
static
HRESULT
STDMETHODCALLTYPE
async_action_GetRuntimeClassName
(
IAsyncAction
*
iface
,
HSTRING
*
class_name
)
{
FIXME
(
"iface %p, class_name %p stub!
\n
"
,
iface
,
class_name
);
return
E_NOTIMPL
;
}
static
HRESULT
STDMETHODCALLTYPE
async_action_GetTrustLevel
(
IAsyncAction
*
iface
,
TrustLevel
*
trust_level
)
{
FIXME
(
"iface %p, trust_level %p stub!
\n
"
,
iface
,
trust_level
);
return
E_NOTIMPL
;
}
static
HRESULT
STDMETHODCALLTYPE
async_action_put_Completed
(
IAsyncAction
*
iface
,
IAsyncActionCompletedHandler
*
handler
)
{
FIXME
(
"iface %p, handler %p stub!
\n
"
,
iface
,
handler
);
return
E_NOTIMPL
;
}
static
HRESULT
STDMETHODCALLTYPE
async_action_get_Completed
(
IAsyncAction
*
iface
,
IAsyncActionCompletedHandler
**
handler
)
{
FIXME
(
"iface %p, handler %p stub!
\n
"
,
iface
,
handler
);
return
E_NOTIMPL
;
}
static
HRESULT
STDMETHODCALLTYPE
async_action_GetResults
(
IAsyncAction
*
iface
)
{
FIXME
(
"iface %p stub!
\n
"
,
iface
);
return
E_NOTIMPL
;
}
static
const
IAsyncActionVtbl
async_action_vtbl
=
{
async_action_QueryInterface
,
async_action_AddRef
,
async_action_Release
,
async_action_GetIids
,
async_action_GetRuntimeClassName
,
async_action_GetTrustLevel
,
async_action_put_Completed
,
async_action_get_Completed
,
async_action_GetResults
,
};
static
HRESULT
STDMETHODCALLTYPE
async_info_QueryInterface
(
IAsyncInfo
*
iface
,
REFIID
iid
,
void
**
out
)
{
struct
async_action
*
action
=
impl_from_IAsyncInfo
(
iface
);
return
IAsyncAction_QueryInterface
(
&
action
->
IAsyncAction_iface
,
iid
,
out
);
}
static
ULONG
STDMETHODCALLTYPE
async_info_AddRef
(
IAsyncInfo
*
iface
)
{
struct
async_action
*
action
=
impl_from_IAsyncInfo
(
iface
);
return
IAsyncAction_AddRef
(
&
action
->
IAsyncAction_iface
);
}
static
ULONG
STDMETHODCALLTYPE
async_info_Release
(
IAsyncInfo
*
iface
)
{
struct
async_action
*
action
=
impl_from_IAsyncInfo
(
iface
);
return
IAsyncAction_AddRef
(
&
action
->
IAsyncAction_iface
);
}
static
HRESULT
STDMETHODCALLTYPE
async_info_GetIids
(
IAsyncInfo
*
iface
,
ULONG
*
iid_count
,
IID
**
iids
)
{
struct
async_action
*
action
=
impl_from_IAsyncInfo
(
iface
);
return
IAsyncAction_GetIids
(
&
action
->
IAsyncAction_iface
,
iid_count
,
iids
);
}
static
HRESULT
STDMETHODCALLTYPE
async_info_GetRuntimeClassName
(
IAsyncInfo
*
iface
,
HSTRING
*
class_name
)
{
struct
async_action
*
action
=
impl_from_IAsyncInfo
(
iface
);
return
IAsyncAction_GetRuntimeClassName
(
&
action
->
IAsyncAction_iface
,
class_name
);
}
static
HRESULT
STDMETHODCALLTYPE
async_info_GetTrustLevel
(
IAsyncInfo
*
iface
,
TrustLevel
*
trust_level
)
{
struct
async_action
*
action
=
impl_from_IAsyncInfo
(
iface
);
return
IAsyncAction_GetTrustLevel
(
&
action
->
IAsyncAction_iface
,
trust_level
);
}
static
HRESULT
STDMETHODCALLTYPE
async_info_get_Id
(
IAsyncInfo
*
iface
,
UINT32
*
id
)
{
FIXME
(
"iface %p, id %p stub!
\n
"
,
iface
,
id
);
return
E_NOTIMPL
;
}
static
HRESULT
STDMETHODCALLTYPE
async_info_get_Status
(
IAsyncInfo
*
iface
,
AsyncStatus
*
status
)
{
FIXME
(
"iface %p, status %p stub!
\n
"
,
iface
,
status
);
return
E_NOTIMPL
;
}
static
HRESULT
STDMETHODCALLTYPE
async_info_get_ErrorCode
(
IAsyncInfo
*
iface
,
HRESULT
*
error_code
)
{
FIXME
(
"iface %p, error_code %p stub!
\n
"
,
iface
,
error_code
);
return
E_NOTIMPL
;
}
static
HRESULT
STDMETHODCALLTYPE
async_info_Cancel
(
IAsyncInfo
*
iface
)
{
FIXME
(
"iface %p stub!
\n
"
,
iface
);
return
E_NOTIMPL
;
}
static
HRESULT
STDMETHODCALLTYPE
async_info_Close
(
IAsyncInfo
*
iface
)
{
FIXME
(
"iface %p stub!
\n
"
,
iface
);
return
E_NOTIMPL
;
}
static
const
IAsyncInfoVtbl
async_info_vtbl
=
{
async_info_QueryInterface
,
async_info_AddRef
,
async_info_Release
,
async_info_GetIids
,
async_info_GetRuntimeClassName
,
async_info_GetTrustLevel
,
async_info_get_Id
,
async_info_get_Status
,
async_info_get_ErrorCode
,
async_info_Cancel
,
async_info_Close
,
};
static
HRESULT
async_action_create
(
IAsyncAction
**
ret
)
{
struct
async_action
*
object
;
*
ret
=
NULL
;
if
(
!
(
object
=
calloc
(
1
,
sizeof
(
*
object
))))
return
E_OUTOFMEMORY
;
object
->
IAsyncAction_iface
.
lpVtbl
=
&
async_action_vtbl
;
object
->
IAsyncInfo_iface
.
lpVtbl
=
&
async_info_vtbl
;
object
->
refcount
=
1
;
*
ret
=
&
object
->
IAsyncAction_iface
;
return
S_OK
;
}
struct
work_item
{
IWorkItemHandler
*
handler
;
IAsyncAction
*
action
;
};
static
void
release_work_item
(
struct
work_item
*
item
)
{
IWorkItemHandler_Release
(
item
->
handler
);
IAsyncAction_Release
(
item
->
action
);
free
(
item
);
}
static
HRESULT
alloc_work_item
(
IWorkItemHandler
*
handler
,
struct
work_item
**
ret
)
{
struct
work_item
*
object
;
HRESULT
hr
;
*
ret
=
NULL
;
if
(
!
(
object
=
calloc
(
1
,
sizeof
(
*
object
))))
return
E_OUTOFMEMORY
;
if
(
FAILED
(
hr
=
async_action_create
(
&
object
->
action
)))
{
free
(
object
);
return
hr
;
}
IWorkItemHandler_AddRef
((
object
->
handler
=
handler
));
*
ret
=
object
;
return
S_OK
;
}
static
void
work_item_invoke_release
(
struct
work_item
*
item
)
{
IWorkItemHandler_Invoke
(
item
->
handler
,
item
->
action
);
release_work_item
(
item
);
}
static
DWORD
WINAPI
sliced_thread_proc
(
void
*
arg
)
{
struct
work_item
*
item
=
arg
;
work_item_invoke_release
(
item
);
return
0
;
}
struct
thread_pool
{
INIT_ONCE
init_once
;
TP_POOL
*
pool
;
};
static
struct
thread_pool
pools
[
3
];
static
BOOL
CALLBACK
pool_init_once
(
INIT_ONCE
*
init_once
,
void
*
param
,
void
**
context
)
{
struct
thread_pool
*
pool
=
param
;
if
(
!
(
pool
->
pool
=
CreateThreadpool
(
NULL
)))
return
FALSE
;
SetThreadpoolThreadMaximum
(
pool
->
pool
,
10
);
return
TRUE
;
}
static
void
CALLBACK
pool_work_callback
(
TP_CALLBACK_INSTANCE
*
instance
,
void
*
context
,
TP_WORK
*
work
)
{
struct
work_item
*
item
=
context
;
work_item_invoke_release
(
item
);
}
static
HRESULT
submit_threadpool_work
(
struct
work_item
*
item
,
WorkItemPriority
priority
,
IAsyncAction
**
action
)
{
struct
thread_pool
*
pool
;
TP_WORK
*
work
;
assert
(
priority
==
WorkItemPriority_Low
||
priority
==
WorkItemPriority_Normal
||
priority
==
WorkItemPriority_High
);
pool
=
&
pools
[
priority
+
1
];
if
(
!
InitOnceExecuteOnce
(
&
pool
->
init_once
,
pool_init_once
,
pool
,
NULL
))
return
E_FAIL
;
if
(
!
(
work
=
CreateThreadpoolWork
(
pool_work_callback
,
item
,
NULL
)))
return
E_FAIL
;
IAsyncAction_AddRef
((
*
action
=
item
->
action
));
SubmitThreadpoolWork
(
work
);
return
S_OK
;
}
static
HRESULT
submit_standalone_thread_work
(
struct
work_item
*
item
,
WorkItemPriority
priority
,
IAsyncAction
**
action
)
{
HANDLE
thread
;
if
(
!
(
thread
=
CreateThread
(
NULL
,
0
,
sliced_thread_proc
,
item
,
priority
==
WorkItemPriority_Normal
?
0
:
CREATE_SUSPENDED
,
NULL
)))
{
WARN
(
"Failed to create a thread, error %ld.
\n
"
,
GetLastError
());
return
HRESULT_FROM_WIN32
(
GetLastError
());
}
IAsyncAction_AddRef
((
*
action
=
item
->
action
));
if
(
priority
!=
WorkItemPriority_Normal
)
{
SetThreadPriority
(
thread
,
priority
==
WorkItemPriority_High
?
THREAD_PRIORITY_HIGHEST
:
THREAD_PRIORITY_LOWEST
);
ResumeThread
(
thread
);
}
CloseHandle
(
thread
);
return
S_OK
;
}
static
HRESULT
run_async
(
IWorkItemHandler
*
handler
,
WorkItemPriority
priority
,
WorkItemOptions
options
,
IAsyncAction
**
action
)
{
struct
work_item
*
item
;
HRESULT
hr
;
*
action
=
NULL
;
if
(
!
handler
)
return
E_INVALIDARG
;
if
(
priority
<
WorkItemPriority_Low
||
priority
>
WorkItemPriority_High
)
return
E_INVALIDARG
;
if
(
FAILED
(
hr
=
alloc_work_item
(
handler
,
&
item
)))
return
hr
;
if
(
options
==
WorkItemOptions_TimeSliced
)
hr
=
submit_standalone_thread_work
(
item
,
priority
,
action
);
else
hr
=
submit_threadpool_work
(
item
,
priority
,
action
);
if
(
FAILED
(
hr
))
release_work_item
(
item
);
return
hr
;
}
static
HRESULT
STDMETHODCALLTYPE
threadpool_factory_QueryInterface
(
static
HRESULT
STDMETHODCALLTYPE
threadpool_factory_QueryInterface
(
IActivationFactory
*
iface
,
REFIID
iid
,
void
**
out
)
IActivationFactory
*
iface
,
REFIID
iid
,
void
**
out
)
{
{
...
@@ -195,23 +571,26 @@ static HRESULT STDMETHODCALLTYPE threadpool_statics_GetTrustLevel(
...
@@ -195,23 +571,26 @@ static HRESULT STDMETHODCALLTYPE threadpool_statics_GetTrustLevel(
static
HRESULT
STDMETHODCALLTYPE
threadpool_statics_RunAsync
(
static
HRESULT
STDMETHODCALLTYPE
threadpool_statics_RunAsync
(
IThreadPoolStatics
*
iface
,
IWorkItemHandler
*
handler
,
IAsyncAction
**
operation
)
IThreadPoolStatics
*
iface
,
IWorkItemHandler
*
handler
,
IAsyncAction
**
operation
)
{
{
FIXME
(
"iface %p, handler %p, operation %p stub!
\n
"
,
iface
,
handler
,
operation
);
TRACE
(
"iface %p, handler %p, operation %p.
\n
"
,
iface
,
handler
,
operation
);
return
E_NOTIMPL
;
return
run_async
(
handler
,
WorkItemPriority_Normal
,
WorkItemOptions_None
,
operation
);
}
}
static
HRESULT
STDMETHODCALLTYPE
threadpool_statics_RunWithPriorityAsync
(
static
HRESULT
STDMETHODCALLTYPE
threadpool_statics_RunWithPriorityAsync
(
IThreadPoolStatics
*
iface
,
IWorkItemHandler
*
handler
,
WorkItemPriority
priority
,
IAsyncAction
**
operation
)
IThreadPoolStatics
*
iface
,
IWorkItemHandler
*
handler
,
WorkItemPriority
priority
,
IAsyncAction
**
operation
)
{
{
FIXME
(
"iface %p, handler %p, priority %d, operation %p stub!
\n
"
,
iface
,
handler
,
priority
,
operation
);
TRACE
(
"iface %p, handler %p, priority %d, operation %p.
\n
"
,
iface
,
handler
,
priority
,
operation
);
return
E_NOTIMPL
;
return
run_async
(
handler
,
priority
,
WorkItemOptions_None
,
operation
);
}
}
static
HRESULT
STDMETHODCALLTYPE
threadpool_statics_RunWithPriorityAndOptionsAsync
(
static
HRESULT
STDMETHODCALLTYPE
threadpool_statics_RunWithPriorityAndOptionsAsync
(
IThreadPoolStatics
*
iface
,
IWorkItemHandler
*
handler
,
WorkItemPriority
priority
,
IThreadPoolStatics
*
iface
,
IWorkItemHandler
*
handler
,
WorkItemPriority
priority
,
WorkItemOptions
options
,
IAsyncAction
**
operation
)
WorkItemOptions
options
,
IAsyncAction
**
operation
)
{
{
FIXME
(
"iface %p, handler %p, priority %d, options %d, operation %p stub!
\n
"
,
iface
,
handler
,
priority
,
options
,
operation
);
TRACE
(
"iface %p, handler %p, priority %d, options %d, operation %p.
\n
"
,
iface
,
handler
,
priority
,
options
,
operation
);
return
E_NOTIMPL
;
return
run_async
(
handler
,
priority
,
options
,
operation
);
}
}
static
const
struct
IThreadPoolStaticsVtbl
threadpool_statics_vtbl
=
static
const
struct
IThreadPoolStaticsVtbl
threadpool_statics_vtbl
=
...
...
dlls/threadpoolwinrt/tests/Makefile.in
0 → 100644
View file @
0f25fadb
TESTDLL
=
threadpoolwinrt.dll
IMPORTS
=
combase uuid
C_SRCS
=
\
threadpool.c
dlls/threadpoolwinrt/tests/threadpool.c
0 → 100644
View file @
0f25fadb
/*
* Copyright 2022 Nikolay Sivov for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winstring.h"
#include "initguid.h"
#include "roapi.h"
#define WIDL_using_Windows_Foundation
#define WIDL_using_Windows_Foundation_Collections
#include "windows.foundation.h"
#define WIDL_using_Windows_System_Threading
#include "windows.system.threading.h"
#include "wine/test.h"
#define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
static
void
check_interface_
(
unsigned
int
line
,
void
*
iface_ptr
,
REFIID
iid
,
BOOL
supported
)
{
IUnknown
*
iface
=
iface_ptr
;
HRESULT
hr
,
expected_hr
;
IUnknown
*
unk
;
expected_hr
=
supported
?
S_OK
:
E_NOINTERFACE
;
hr
=
IUnknown_QueryInterface
(
iface
,
iid
,
(
void
**
)
&
unk
);
ok_
(
__FILE__
,
line
)(
hr
==
expected_hr
,
"Got hr %#lx, expected %#lx.
\n
"
,
hr
,
expected_hr
);
if
(
SUCCEEDED
(
hr
))
IUnknown_Release
(
unk
);
}
static
const
WCHAR
*
threadpool_class_name
=
L"Windows.System.Threading.ThreadPool"
;
static
void
test_interfaces
(
void
)
{
IThreadPoolStatics
*
threadpool_statics
;
IActivationFactory
*
factory
;
HSTRING
classid
;
HRESULT
hr
;
hr
=
RoInitialize
(
RO_INIT_MULTITHREADED
);
ok
(
SUCCEEDED
(
hr
),
"Unexpected hr %#lx.
\n
"
,
hr
);
hr
=
WindowsCreateString
(
threadpool_class_name
,
wcslen
(
threadpool_class_name
),
&
classid
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
hr
=
RoGetActivationFactory
(
classid
,
&
IID_IActivationFactory
,
(
void
**
)
&
factory
);
ok
(
hr
==
S_OK
||
broken
(
hr
==
REGDB_E_CLASSNOTREG
),
"Unexpected hr %#lx.
\n
"
,
hr
);
if
(
hr
==
REGDB_E_CLASSNOTREG
)
{
win_skip
(
"%s runtimeclass not registered, skipping tests.
\n
"
,
wine_dbgstr_w
(
threadpool_class_name
));
return
;
}
check_interface
(
factory
,
&
IID_IInspectable
,
TRUE
);
check_interface
(
factory
,
&
IID_IAgileObject
,
TRUE
);
check_interface
(
factory
,
&
IID_IThreadPoolStatics
,
TRUE
);
hr
=
IActivationFactory_QueryInterface
(
factory
,
&
IID_IThreadPoolStatics
,
(
void
**
)
&
threadpool_statics
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
check_interface
(
threadpool_statics
,
&
IID_IInspectable
,
TRUE
);
check_interface
(
threadpool_statics
,
&
IID_IAgileObject
,
TRUE
);
IThreadPoolStatics_Release
(
threadpool_statics
);
IActivationFactory_Release
(
factory
);
WindowsDeleteString
(
classid
);
RoUninitialize
();
}
struct
work_item
{
IWorkItemHandler
IWorkItemHandler_iface
;
LONG
refcount
;
HANDLE
event
;
};
static
struct
work_item
*
impl_from_IWorkItemHandler
(
IWorkItemHandler
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
work_item
,
IWorkItemHandler_iface
);
}
static
HRESULT
STDMETHODCALLTYPE
work_item_QueryInterface
(
IWorkItemHandler
*
iface
,
REFIID
riid
,
void
**
obj
)
{
if
(
IsEqualIID
(
riid
,
&
IID_IWorkItemHandler
)
||
IsEqualIID
(
riid
,
&
IID_IUnknown
))
{
*
obj
=
iface
;
IWorkItemHandler_AddRef
(
iface
);
return
S_OK
;
}
*
obj
=
NULL
;
return
E_NOINTERFACE
;
}
static
ULONG
STDMETHODCALLTYPE
work_item_AddRef
(
IWorkItemHandler
*
iface
)
{
struct
work_item
*
item
=
impl_from_IWorkItemHandler
(
iface
);
return
InterlockedIncrement
(
&
item
->
refcount
);
}
static
ULONG
STDMETHODCALLTYPE
work_item_Release
(
IWorkItemHandler
*
iface
)
{
struct
work_item
*
item
=
impl_from_IWorkItemHandler
(
iface
);
ULONG
refcount
=
InterlockedDecrement
(
&
item
->
refcount
);
if
(
!
refcount
)
{
CloseHandle
(
item
->
event
);
free
(
item
);
}
return
refcount
;
}
static
HRESULT
STDMETHODCALLTYPE
work_item_Invoke
(
IWorkItemHandler
*
iface
,
IAsyncAction
*
action
)
{
struct
work_item
*
item
=
impl_from_IWorkItemHandler
(
iface
);
IAsyncActionCompletedHandler
*
handler
;
IAsyncInfo
*
async_info
;
AsyncStatus
status
;
HRESULT
hr
;
hr
=
IAsyncAction_QueryInterface
(
action
,
&
IID_IAsyncInfo
,
(
void
**
)
&
async_info
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
hr
=
IAsyncInfo_get_Status
(
async_info
,
&
status
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
if
(
SUCCEEDED
(
hr
))
ok
(
status
==
Started
,
"Unexpected status %d.
\n
"
,
status
);
hr
=
IAsyncInfo_Cancel
(
async_info
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
IAsyncInfo_Release
(
async_info
);
hr
=
IAsyncAction_GetResults
(
action
);
todo_wine
ok
(
hr
==
E_ILLEGAL_METHOD_CALL
,
"Unexpected hr %#lx.
\n
"
,
hr
);
handler
=
(
void
*
)
0xdeadbeef
;
hr
=
IAsyncAction_get_Completed
(
action
,
&
handler
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
todo_wine
ok
(
!
handler
,
"Unexpected pointer %p.
\n
"
,
handler
);
hr
=
IAsyncAction_put_Completed
(
action
,
NULL
);
todo_wine
ok
(
hr
==
E_POINTER
,
"Unexpected hr %#lx.
\n
"
,
hr
);
SetEvent
(
item
->
event
);
return
S_OK
;
}
static
const
IWorkItemHandlerVtbl
work_item_vtbl
=
{
work_item_QueryInterface
,
work_item_AddRef
,
work_item_Release
,
work_item_Invoke
,
};
static
HRESULT
create_work_item
(
IWorkItemHandler
**
item
)
{
struct
work_item
*
object
;
*
item
=
NULL
;
if
(
!
(
object
=
calloc
(
1
,
sizeof
(
*
object
))))
return
E_OUTOFMEMORY
;
object
->
IWorkItemHandler_iface
.
lpVtbl
=
&
work_item_vtbl
;
object
->
refcount
=
1
;
object
->
event
=
CreateEventW
(
NULL
,
FALSE
,
FALSE
,
NULL
);
*
item
=
&
object
->
IWorkItemHandler_iface
;
return
S_OK
;
}
static
void
test_RunAsync
(
void
)
{
IActivationFactory
*
factory
=
NULL
;
IThreadPoolStatics
*
threadpool_statics
;
IWorkItemHandler
*
item_iface
;
struct
work_item
*
item
;
IAsyncAction
*
action
;
HSTRING
classid
;
HRESULT
hr
;
DWORD
ret
;
hr
=
RoInitialize
(
RO_INIT_MULTITHREADED
);
ok
(
SUCCEEDED
(
hr
),
"Unexpected hr %#lx.
\n
"
,
hr
);
hr
=
WindowsCreateString
(
threadpool_class_name
,
wcslen
(
threadpool_class_name
),
&
classid
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
hr
=
RoGetActivationFactory
(
classid
,
&
IID_IActivationFactory
,
(
void
**
)
&
factory
);
ok
(
hr
==
S_OK
||
broken
(
hr
==
REGDB_E_CLASSNOTREG
),
"Unexpected hr %#lx.
\n
"
,
hr
);
if
(
hr
==
REGDB_E_CLASSNOTREG
)
return
;
hr
=
IActivationFactory_QueryInterface
(
factory
,
&
IID_IThreadPoolStatics
,
(
void
**
)
&
threadpool_statics
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
hr
=
IThreadPoolStatics_RunAsync
(
threadpool_statics
,
NULL
,
&
action
);
ok
(
hr
==
E_INVALIDARG
,
"Unexpected hr %#lx.
\n
"
,
hr
);
hr
=
create_work_item
(
&
item_iface
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
item
=
impl_from_IWorkItemHandler
(
item_iface
);
hr
=
IThreadPoolStatics_RunWithPriorityAsync
(
threadpool_statics
,
item_iface
,
WorkItemPriority_High
+
1
,
&
action
);
ok
(
hr
==
E_INVALIDARG
,
"Unexpected hr %#lx.
\n
"
,
hr
);
hr
=
IThreadPoolStatics_RunAsync
(
threadpool_statics
,
item_iface
,
&
action
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ret
=
WaitForSingleObject
(
item
->
event
,
1000
);
ok
(
!
ret
,
"Unexpected wait result %lu.
\n
"
,
ret
);
check_interface
(
action
,
&
IID_IAsyncAction
,
TRUE
);
check_interface
(
action
,
&
IID_IAsyncInfo
,
TRUE
);
check_interface
(
action
,
&
IID_IInspectable
,
TRUE
);
IAsyncAction_Release
(
action
);
hr
=
IThreadPoolStatics_RunWithPriorityAsync
(
threadpool_statics
,
item_iface
,
WorkItemPriority_Normal
,
&
action
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ret
=
WaitForSingleObject
(
item
->
event
,
1000
);
ok
(
!
ret
,
"Unexpected wait result %lu.
\n
"
,
ret
);
IAsyncAction_Release
(
action
);
hr
=
IThreadPoolStatics_RunWithPriorityAndOptionsAsync
(
threadpool_statics
,
item_iface
,
WorkItemPriority_Normal
,
WorkItemOptions_TimeSliced
,
&
action
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ret
=
WaitForSingleObject
(
item
->
event
,
1000
);
ok
(
!
ret
,
"Unexpected wait result %lu.
\n
"
,
ret
);
IAsyncAction_Release
(
action
);
hr
=
IThreadPoolStatics_RunWithPriorityAndOptionsAsync
(
threadpool_statics
,
item_iface
,
WorkItemPriority_Low
,
WorkItemOptions_TimeSliced
,
&
action
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ret
=
WaitForSingleObject
(
item
->
event
,
1000
);
ok
(
!
ret
,
"Unexpected wait result %lu.
\n
"
,
ret
);
IAsyncAction_Release
(
action
);
hr
=
IThreadPoolStatics_RunWithPriorityAndOptionsAsync
(
threadpool_statics
,
item_iface
,
WorkItemPriority_High
,
WorkItemOptions_TimeSliced
,
&
action
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ret
=
WaitForSingleObject
(
item
->
event
,
1000
);
ok
(
!
ret
,
"Unexpected wait result %lu.
\n
"
,
ret
);
IAsyncAction_Release
(
action
);
IWorkItemHandler_Release
(
item_iface
);
IThreadPoolStatics_Release
(
threadpool_statics
);
IActivationFactory_Release
(
factory
);
WindowsDeleteString
(
classid
);
RoUninitialize
();
}
START_TEST
(
threadpool
)
{
test_interfaces
();
test_RunAsync
();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment