* Initial checkin with specs

* Fixed Traceability

* Fixed PVOID on Linux

* Fixed PVOID in threadpool.h

* Forgot to add threadpool.h into the commit, adding it now

* Addressed comments by Matt

* Addressed ALL comments by Matt
This commit is contained in:
Nishikant Deshmukh 2024-09-03 17:35:36 -07:00 коммит произвёл GitHub
Родитель 82c66b2da7
Коммит 8c1dd06fb3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
11 изменённых файлов: 292 добавлений и 16 удалений

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

@ -11,7 +11,7 @@ endif()
#if ((NOT TARGET c_pal) AND (EXISTS ${CMAKE_CURRENT_LIST_DIR}/deps/c-pal/CMakeLists.txt))
# add_subdirectory(deps/c-pal)
# include_directories(${C_PAL_INC_FOLDER})
#endif()
#endif()
if (TARGET c_pal)
RETURN()
@ -93,7 +93,7 @@ set(run_reals_check OFF)
if ((NOT TARGET c_build_tools) AND (EXISTS ${CMAKE_CURRENT_LIST_DIR}/deps/c-build-tools/CMakeLists.txt))
add_subdirectory(deps/c-build-tools)
set_default_build_options()
endif()
endif()
if ((WIN32) AND ("${GBALLOC_LL_TYPE}" STREQUAL "JEMALLOC"))
# Bring in vcpkg
@ -125,37 +125,37 @@ endif()
if ((NOT TARGET macro_utils_c) AND (EXISTS ${CMAKE_CURRENT_LIST_DIR}/deps/macro-utils-c/CMakeLists.txt))
add_subdirectory(deps/macro-utils-c)
include_directories(${MACRO_UTILS_INC_FOLDER})
endif()
endif()
if ((NOT TARGET c_logging_v2) AND (EXISTS ${CMAKE_CURRENT_LIST_DIR}/deps/c-logging/CMakeLists.txt))
add_subdirectory(deps/c-logging)
include_directories(deps/c-logging/v2/inc)
endif()
endif()
if ((NOT TARGET ctest) AND (EXISTS ${CMAKE_CURRENT_LIST_DIR}/deps/ctest/CMakeLists.txt))
add_subdirectory(deps/ctest)
include_directories(${CTEST_INC_FOLDER})
endif()
endif()
if ((NOT TARGET testrunnerswitcher) AND (EXISTS ${CMAKE_CURRENT_LIST_DIR}/deps/c-testrunnerswitcher/CMakeLists.txt))
add_subdirectory(deps/c-testrunnerswitcher)
include_directories(${TESTRUNNERSWITCHER_INC_FOLDER})
endif()
endif()
if ((NOT TARGET umock_c) AND (EXISTS ${CMAKE_CURRENT_LIST_DIR}/deps/umock-c/CMakeLists.txt))
add_subdirectory(deps/umock-c)
include_directories(${UMOCK_C_INC_FOLDER})
endif()
endif()
# Skip for Linux iwyu
if (WIN32)
if (
(NOT TARGET mimalloc-obj) AND
(NOT TARGET mimalloc-obj) AND
(${GBALLOC_LL_TYPE} STREQUAL "MIMALLOC") AND
(EXISTS ${CMAKE_CURRENT_LIST_DIR}/deps/mimalloc/CMakeLists.txt)
)
set(MI_BUILD_SHARED OFF CACHE BOOL "Build shared library" FORCE) #not building a dll allows building on 32 bit, otherwise there's some errors on init.c about not finding a imported symbol
set(MI_BUILD_TESTS OFF CACHE BOOL "Build test executables" FORCE)
set(MI_BUILD_TESTS OFF CACHE BOOL "Build test executables" FORCE)
#for mimalloc disable this warning: Warning C4459: declaration of 'os_page_size' hides global declaration
#for mimalloc disable this warning: Warning C4100: 'try_alignment': unreferenced formal parameter
#for mimalloc disable this warning: warning C4505: 'mi_os_get_aligned_hint': unreferenced local function has been removed
@ -169,7 +169,7 @@ if (WIN32)
add_subdirectory(deps/mimalloc)
include_directories(deps/mimalloc/include)
set(CMAKE_C_FLAGS ${PREV_CMAKE_C_FLAGS})
set(CMAKE_CXX_FLAGS ${PREV_CMAKE_CXX_FLAGS})
endif()
@ -185,7 +185,7 @@ set(run_reals_check ${original_run_reals_check})
include(CTest)
enable_testing()
set(C_PAL_INC_FOLDER
set(C_PAL_INC_FOLDER
${CMAKE_CURRENT_LIST_DIR}/interfaces/inc
${CMAKE_CURRENT_LIST_DIR}/common/inc
${CMAKE_CURRENT_LIST_DIR}/c_pal_ll/interfaces/inc

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

@ -21,7 +21,7 @@ The lifetime of the execution engine should supersede the lifetime of the `threa
```c
typedef struct THREADPOOL_TAG THREADPOOL;
typedef struct TIMER_INSTANCE_TAG* TIMER_INSTANCE_HANDLE;
typedef struct THREADPOOL_WORK_ITEM_TAG* THREADPOOL_WORK_ITEM_HANDLE;
typedef void (*THREADPOOL_WORK_FUNCTION)(void* context);
THANDLE_TYPE_DECLARE(THREADPOOL);
@ -31,6 +31,12 @@ MOCKABLE_FUNCTION(, THANDLE(THREADPOOL), threadpool_create, EXECUTION_ENGINE_HAN
MOCKABLE_FUNCTION(, int, threadpool_open, THANDLE(THREADPOOL), threadpool);
MOCKABLE_FUNCTION(, void, threadpool_close, THANDLE(THREADPOOL), threadpool);
MOCKABLE_FUNCTION(, THREADPOOL_WORK_ITEM_HANDLE, threadpool_create_work_item, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_FUNCTION, work_function, void*, work_function_context);
MOCKABLE_FUNCTION(, int, threadpool_schedule_work_item, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_ITEM_HANDLE, work_item_context);
MOCKABLE_FUNCTION(, void, threadpool_destroy_work_item, THREADPOOL_WORK_ITEM_HANDLE, work_item_context);
MOCKABLE_FUNCTION(, int, threadpool_schedule_work, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_FUNCTION, work_function, void*, work_function_context);
MOCKABLE_FUNCTION(, int, threadpool_timer_start, THANDLE(THREADPOOL), threadpool, uint32_t, start_delay_ms, uint32_t, timer_period_ms, THREADPOOL_WORK_FUNCTION, work_function, void*, work_function_context, TIMER_INSTANCE_HANDLE*, timer_handle);
@ -104,6 +110,56 @@ MOCKABLE_FUNCTION(, void, threadpool_close, THREADPOOL_HANDLE, threadpool);
**NON_THREADPOOL_01_019: [** If `threadpool` is not OPEN, `threadpool_close` shall return. **]**
### threadpool_create_work_item
```c
MOCKABLE_FUNCTION(, THREADPOOL_WORK_ITEM_HANDLE, threadpool_create_work_item, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_FUNCTION, work_function, void*, work_function_context);
```
`threadpool_create_work_item` creates a work item to be executed by the threadpool. This function separates the creation of the work item from scheduling it so that threadpool_schedule_work_item can be called later and cannot fail.
**NON_THREADPOOL_05_001: [** If `threadpool` is `NULL`, `threadpool_create_work_item` shall fail and return a `NULL` value. **]**
**NON_THREADPOOL_05_002: [** If `work_function` is `NULL`, `threadpool_create_work_item` shall fail and return a `NULL` value. **]**
**NON_THREADPOOL_05_003: [** Otherwise `threadpool_create_work_item` shall allocate a context of type `THREADPOOL_WORK_ITEM_HANDLE` to save threadpool related variables. **]**
**NON_THREADPOOL_05_004: [** If any error occurs, `threadpool_create_work_item` shall fail and return a `NULL` value. **]**
**NON_THREADPOOL_05_005: [** `threadpool_create_work_item` shall create an individual work item context of type `THREADPOOL_WORK_ITEM_HANDLE` **]**
**NON_THREADPOOL_05_006: [** If there are no errors then the work item of type `THREADPOOL_WORK_ITEM_HANDLE` is created and returned to the caller. **]**
**NON_THREADPOOL_05_007: [** If any error occurs, `threadpool_create_work_item` shall fail, free the newly created context and return a `NULL` value. **]**
### threadpool_schedule_work_item
```c
MOCKABLE_FUNCTION(, int, threadpool_schedule_work_item, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_ITEM_HANDLE, work_item_context);
```
`threadpool_schedule_work_item` schedules a work item to be executed by the threadpool. This API is called multiple times on the same `THREADPOOL_WORK_ITEM_HANDLE` and fails only if the arguments are passed `NULL`.
**NON_THREADPOOL_05_008: [** If `threadpool` is NULL, `threadpool_schedule_work_item` shall fail and return a `non-zero` value. **]**
**NON_THREADPOOL_05_009: [** If `work_item_context` is NULL, `threadpool_schedule_work_item` shall fail and return a `non-zero` value. **]**
**NON_THREADPOOL_05_010: [** `threadpool_schedule_work_item` shall submit the threadpool work item for execution. **]**
### threadpool_destroy_work_item
```c
MOCKABLE_FUNCTION(, void, threadpool_destroy_work_item, THREADPOOL_WORK_ITEM_HANDLE, work_item_context);
```
`threadpool_destroy_work_item` closes and frees all the member variables in the context of type `THREADPOOL_WORK_ITEM_HANDLE` and then frees the context
**NON_THREADPOOL_05_011: [** If `work_item_context` is `NULL`, `threadpool_destroy_work_item` shall fail and not do anything before returning. **]**
**NON_THREADPOOL_05_012: [** `threadpool_destroy_work_item` shall close and free all the members of `THREADPOOL_WORK_ITEM_HANDLE`. **]**
**NON_THREADPOOL_05_013: [** `threadpool_destroy_work_item` shall free the `work_item_context` of type `THREADPOOL_WORK_ITEM_HANDLE`. **]**
### threadpool_schedule_work
```c

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

@ -22,7 +22,7 @@ extern "C" {
typedef struct THREADPOOL_TAG THREADPOOL;
typedef struct TIMER_INSTANCE_TAG* TIMER_INSTANCE_HANDLE;
typedef struct THREADPOOL_WORK_ITEM_TAG* THREADPOOL_WORK_ITEM_HANDLE;
typedef void (*THREADPOOL_WORK_FUNCTION)(void* context);
THANDLE_TYPE_DECLARE(THREADPOOL);
@ -32,6 +32,12 @@ MOCKABLE_FUNCTION(, THANDLE(THREADPOOL), threadpool_create, EXECUTION_ENGINE_HAN
MOCKABLE_FUNCTION(, int, threadpool_open, THANDLE(THREADPOOL), threadpool);
MOCKABLE_FUNCTION(, void, threadpool_close, THANDLE(THREADPOOL), threadpool);
MOCKABLE_FUNCTION(, THREADPOOL_WORK_ITEM_HANDLE, threadpool_create_work_item, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_FUNCTION, work_function, void*, work_function_context);
MOCKABLE_FUNCTION(, int, threadpool_schedule_work_item, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_ITEM_HANDLE, work_item_context);
MOCKABLE_FUNCTION(, void, threadpool_destroy_work_item, THREADPOOL_WORK_ITEM_HANDLE, work_item_context);
MOCKABLE_FUNCTION(, int, threadpool_schedule_work, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_FUNCTION, work_function, void*, work_function_context);
MOCKABLE_FUNCTION(, int, threadpool_timer_start, THANDLE(THREADPOOL), threadpool, uint32_t, start_delay_ms, uint32_t, timer_period_ms, THREADPOOL_WORK_FUNCTION, work_function, void*, work_function_context, TIMER_INSTANCE_HANDLE*, timer_handle);

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

@ -67,7 +67,7 @@ The guard prevents any work from happening, but the event callback can still be
```C
typedef struct THREADPOOL_TAG THREADPOOL;
typedef struct TIMER_INSTANCE_TAG* TIMER_INSTANCE_HANDLE;
typedef struct THREADPOOL_WORK_ITEM_TAG* THREADPOOL_WORK_ITEM_HANDLE;
typedef void (*THREADPOOL_WORK_FUNCTION)(void* context);
THANDLE_TYPE_DECLARE(THREADPOOL);
@ -77,6 +77,12 @@ MOCKABLE_FUNCTION(, THANDLE(THREADPOOL), threadpool_create, EXECUTION_ENGINE_HAN
MOCKABLE_FUNCTION(, int, threadpool_open, THANDLE(THREADPOOL), threadpool);
MOCKABLE_FUNCTION(, void, threadpool_close, THANDLE(THREADPOOL), threadpool);
MOCKABLE_FUNCTION(, THREADPOOL_WORK_ITEM_HANDLE, threadpool_create_work_item, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_FUNCTION, work_function, void*, work_function_context);
MOCKABLE_FUNCTION(, int, threadpool_schedule_work_item, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_ITEM_HANDLE, work_item_context);
MOCKABLE_FUNCTION(, void, threadpool_work_context_destroy, THREADPOOL_WORK_ITEM_HANDLE, work_item_context);
MOCKABLE_FUNCTION(, int, threadpool_schedule_work, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_FUNCTION, work_function, void*, work_function_context);
MOCKABLE_FUNCTION(, int, threadpool_timer_start, THANDLE(THREADPOOL), threadpool, uint32_t, start_delay_ms, uint32_t, timer_period_ms, THREADPOOL_WORK_FUNCTION, work_function, void*, work_function_context, TIMER_INSTANCE_HANDLE*, timer_handle);
@ -381,3 +387,67 @@ static int threadpool_work_func(void* param);
**SRS_THREADPOOL_LINUX_07_084: [** If the work item function is not `NULL`, `threadpool_work_func` shall execute it with `work_function_ctx`. **]**
**SRS_THREADPOOL_LINUX_07_085: [** `threadpool_work_func` shall loop until `threadpool_close` or `threadpool_destroy` is called. **]**
### threadpool_create_work_item
```c
MOCKABLE_FUNCTION(, THREADPOOL_WORK_ITEM_HANDLE, threadpool_create_work_item, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_FUNCTION, work_function, void*, work_function_context);
```
`threadpool_create_work_item` creates a work item to be executed by the threadpool.
**S_R_S THREADPOOL_LINUX_05_001: [** If `threadpool` is `NULL`, `threadpool_create_work_item` shall fail and return a `NULL` value. **]**
**S_R_S_THREADPOOL_LINUX_05_002: [** If `work_function` is `NULL`, `threadpool_create_work_item` shall fail and return a `NULL` value. **]**
**S_R_S_THREADPOOL_LINUX_05_003: [** `threadpool_create_work_item` shall allocate memory for `threadpool_work_item` of type `THREADPOOL_WORK_ITEM_HANDLE`. **]**
**S_R_S_THREADPOOL_LINUX_05_004: [** If the `malloc` fails and `threadpool_work_item` is `NULL` then log the error and return `NULL`. **]**
**S_R_S_THREADPOOL_LINUX_05_005: [** `threadpool_create_work_item` shall copy the `work_function` and `work_function_context` into the `threadpool_work_item` and return `threadpool_work_item` to indicate success. **]**
### threadpool_schedule_work_item
```c
MOCKABLE_FUNCTION(, int, threadpool_schedule_work_item, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_ITEM_HANDLE, work_item);
```
`threadpool_schedule_work_item` schedules a work item to be executed by the threadpool.
**S_R_S_THREADPOOL_LINUX_05_006: [** If `threadpool` is `NULL`, `threadpool_schedule_work_item` shall fail and return a non-zero value. **]**
**S_R_S_THREADPOOL_LINUX_05_007: [** If `work_item` is `NULL`, `threadpool_schedule_work_item` shall fail and return a non-zero value. **]**
**S_R_S_THREADPOOL_LINUX_05_008: [** `threadpool_schedule_work_item` shall call `sm_exec_begin`. **]**
**S_R_S_THREADPOOL_LINUX_05_009: [** If `sm_exec_begin` returns `SM_EXEC_REFUSED`, `threadpool_schedule_work_item` shall fail and return a non-zero value. **]**
**S_R_S_THREADPOOL_LINUX_05_010: [** `threadpool_schedule_work_item` shall acquire the `SRW lock` in shared mode by calling `srw_lock_acquire_shared`. **]**
**S_R_S_THREADPOOL_LINUX_05_011: [** `threadpool_schedule_work_item` shall increment the `insert_pos`. **]**
**S_R_S_THREADPOOL_LINUX_05_012: [** If task state is `TASK_NOT_USED`, `threadpool_schedule_work_item` shall set the current task state to `TASK_INITIALIZING`. **]**
**S_R_S_THREADPOOL_LINUX_05_013: [** Otherwise, `threadpool_schedule_work_item` shall release the shared SRW lock by calling `srw_lock_release_shared` and increase `task_array` capacity: **]**
**S_R_S_THREADPOOL_LINUX_05_014: [** If reallocating the task array fails, `threadpool_schedule_work_item` shall fail and return a `NULL` value. **]**
**S_R_S_THREADPOOL_LINUX_05_015: [** `threadpool_schedule_work_item` shall copy the `work_function` and `work_function_context` from `work_item` into insert position in the task array and return `0` on success. **]**
**S_R_S_THREADPOOL_LINUX_05_016: [** `threadpool_schedule_work_item` shall set the `task_state` to `TASK_WAITING` and then release the shared SRW lock. **]**
**S_R_S_THREADPOOL_LINUX_05_017: [** `threadpool_schedule_work_item` shall unblock the `threadpool` semaphore by calling `sem_post`. **]**
**S_R_S_THREADPOOL_LINUX_05_018: [** `threadpool_schedule_work_item` shall return `0` on success. **]**
**S_R_S_THREADPOOL_LINUX_05_019: [** `threadpool_schedule_work_item` shall call `sm_exec_end`. **]**
### threadpool_destroy_work_item
```c
MOCKABLE_FUNCTION(, void, threadpool_destroy_work_item, THREADPOOL_WORK_ITEM_HANDLE, work_item_context);
```
`threadpool_work_context_destroy` Does nothing and a placeholder for WIN32 equivalent function stub
**S_R_S_THREADPOOL_LINUX_05_020: [** Free memory allocated to the work item of type `THREADPOOL_WORK_ITEM_HANDLE` created in `threadpool_create_work_item`. **]**

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

@ -36,6 +36,9 @@ extern "C" {
THANDLE(THREADPOOL) real_threadpool_create(EXECUTION_ENGINE_HANDLE execution_engine);
int real_threadpool_open(THANDLE(THREADPOOL) threadpool);
void real_threadpool_close(THANDLE(THREADPOOL) threadpool);
THREADPOOL_WORK_ITEM_HANDLE real_threadpool_create_work_item(THANDLE(THREADPOOL) threadpool, THREADPOOL_WORK_FUNCTION work_function, void* work_function_context);
int real_threadpool_schedule_work_item(THANDLE(THREADPOOL) threadpool, THREADPOOL_WORK_ITEM_HANDLE work_item_context);
void real_threadpool_destroy_work_item(THREADPOOL_WORK_ITEM_HANDLE work_item_context);
int real_threadpool_schedule_work(THANDLE(THREADPOOL) threadpool, THREADPOOL_WORK_FUNCTION work_function, void* work_function_context);
int real_threadpool_timer_start(THANDLE(THREADPOOL) threadpool, uint32_t start_delay_ms, uint32_t timer_period_ms, THREADPOOL_WORK_FUNCTION work_function, void* work_function_context, TIMER_INSTANCE_HANDLE* timer_handle);
int real_threadpool_timer_restart(TIMER_INSTANCE_HANDLE timer, uint32_t start_delay_ms, uint32_t timer_period_ms);

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

@ -6,6 +6,9 @@
#define threadpool_create real_threadpool_create
#define threadpool_open real_threadpool_open
#define threadpool_close real_threadpool_close
#define threadpool_create_work_item real_threadpool_create_work_item
#define threadpool_schedule_work_item real_threadpool_schedule_work_item
#define threadpool_destroy_work_item real_threadpool_destroy_work_item
#define threadpool_schedule_work real_threadpool_schedule_work
#define threadpool_timer_start real_threadpool_timer_start
#define threadpool_timer_restart real_threadpool_timer_restart

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

@ -73,6 +73,14 @@ typedef struct THREADPOOL_TASK_TAG
volatile uint32_t pending_api_calls;
} THREADPOOL_TASK;
typedef struct THREADPOOL_WORK_ITEM_TAG
{
volatile_atomic int32_t task_state;
THREADPOOL_WORK_FUNCTION work_function;
void* work_function_ctx;
volatile uint32_t pending_api_calls;
} THREADPOOL_WORK_ITEM, * THREADPOOL_WORK_ITEM_HANDLE;
typedef struct THREADPOOL_TAG
{
volatile_atomic int32_t run_thread;
@ -507,6 +515,23 @@ void threadpool_close(THANDLE(THREADPOOL) threadpool)
}
}
THREADPOOL_WORK_ITEM_HANDLE threadpool_create_work_item(THANDLE(THREADPOOL) threadpool, THREADPOOL_WORK_FUNCTION work_function, void* work_function_context)
{
LogWarning("Not Implemented: threadpool_create_work_item(%p, %p, %p)", threadpool, work_function, work_function_context);
return NULL;
}
int threadpool_schedule_work_item(THANDLE(THREADPOOL) threadpool, THREADPOOL_WORK_ITEM_HANDLE work_item_context)
{
LogWarning("Not Implemented: threadpool_schedule_work_item(%p)", work_item_context);
return 0;
}
void threadpool_work_context_destroy(THREADPOOL_WORK_ITEM_HANDLE work_item_context)
{
LogWarning("Not Implemented: threadpool_work_context_destroy(%p)", work_item_context);
}
int threadpool_schedule_work(THANDLE(THREADPOOL) threadpool, THREADPOOL_WORK_FUNCTION work_function, void* work_function_ctx)
{
int result;

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

@ -13,7 +13,7 @@ It uses the PTP_POOL associated with the execution engine passed as argument to
```c
typedef struct THREADPOOL_TAG THREADPOOL;
typedef struct TIMER_INSTANCE_TAG* TIMER_INSTANCE_HANDLE;
typedef struct THREADPOOL_WORK_ITEM_TAG* THREADPOOL_WORK_ITEM_HANDLE;
typedef void (*THREADPOOL_WORK_FUNCTION)(void* context);
THANDLE_TYPE_DECLARE(THREADPOOL);
@ -23,6 +23,12 @@ MOCKABLE_FUNCTION(, THANDLE(THREADPOOL), threadpool_create, EXECUTION_ENGINE_HAN
MOCKABLE_FUNCTION(, int, threadpool_open, THANDLE(THREADPOOL), threadpool);
MOCKABLE_FUNCTION(, void, threadpool_close, THANDLE(THREADPOOL), threadpool);
MOCKABLE_FUNCTION(, THREADPOOL_WORK_ITEM_HANDLE, threadpool_create_work_item, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_FUNCTION, work_function, void*, work_function_context);
MOCKABLE_FUNCTION(, int, threadpool_schedule_work_item, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_ITEM_HANDLE, work_item_context);
MOCKABLE_FUNCTION(, void, threadpool_destroy_work_item, THREADPOOL_WORK_ITEM_HANDLE, work_item_context);
MOCKABLE_FUNCTION(, int, threadpool_schedule_work, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_FUNCTION, work_function, void*, work_function_context);
MOCKABLE_FUNCTION(, int, threadpool_timer_start, THANDLE(THREADPOOL), threadpool, uint32_t, start_delay_ms, uint32_t, timer_period_ms, THREADPOOL_WORK_FUNCTION, work_function, void*, work_function_context, TIMER_INSTANCE_HANDLE*, timer_handle);
@ -156,6 +162,21 @@ static VOID CALLBACK on_work_callback(PTP_CALLBACK_INSTANCE instance, PVOID cont
**SRS_THREADPOOL_WIN32_01_039: [** `on_work_callback` shall free the context allocated in `threadpool_schedule_work`. **]**
### on_work_callback_v2
```c
static VOID CALLBACK on_work_callback_v2(PTP_CALLBACK_INSTANCE instance, void* context, PTP_WORK work);
```
`on_work_callback_v2` executes the work function passed to `threadpool_create_work_item`.
**S_R_S_THREADPOOL_WIN32_05_001: [** If `context` is `NULL`, `on_work_callback_v2` shall return. **]**
**S_R_S_THREADPOOL_WIN32_05_002: [** Otherwise `context` shall be used as the context created in `threadpool_create_work_item`. **]**
**S_R_S_THREADPOOL_WIN32_05_003: [** The `work_function` callback passed to `threadpool_create_work_item` shall be called with the `work_function_context` as an argument. `work_function_context` was set inside the `threadpool_create_work_item` as an argument to `CreateThreadpoolContext`. **]**
### threadpool_timer_start
```c
@ -243,3 +264,54 @@ static VOID CALLBACK on_timer_callback(PTP_CALLBACK_INSTANCE instance, PVOID con
**SRS_THREADPOOL_WIN32_42_017: [** Otherwise `context` shall be used as the context created in `threadpool_schedule_work`. **]**
**SRS_THREADPOOL_WIN32_42_018: [** The `work_function` callback passed to `threadpool_schedule_work` shall be called, passing to it the `work_function_context` argument passed to `threadpool_schedule_work`. **]**
### threadpool_create_work_item
```c
MOCKABLE_FUNCTION(, THREADPOOL_WORK_ITEM_HANDLE, threadpool_create_work_item, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_FUNCTION, work_function, void*, work_function_context);
```
`threadpool_create_work_item` creates a work item to be executed by the threadpool.
**S_R_S_THREADPOOL_WIN32_05_004: [** If `threadpool` is `NULL`, `threadpool_create_work_item` shall fail and return a `NULL` value. **]**
**S_R_S_THREADPOOL_WIN32_05_005: [** If `work_function` is `NULL`, `threadpool_create_work_item` shall fail and return a `NULL` value. **]**
**S_R_S_THREADPOOL_WIN32_05_006: [** Otherwise `threadpool_create_work_item` shall allocate a context `work_item_context` of type `THREADPOOL_WORK_ITEM_HANDLE` where `work_function`, `work_function_context`, and `ptp_work` shall be saved. **]**
**S_R_S_THREADPOOL_WIN32_05_007: [** If any error occurs, `threadpool_create_work_item` shall fail and return a `NULL` value. **]**
**S_R_S_THREADPOOL_WIN32_05_008: [** `threadpool_create_work_item` shall create `work_item_context` member variable `ptp_work` of type `PTP_WORK` by calling `CreateThreadpoolWork` to set the callback function as `on_work_callback_v2`. **]**
**S_R_S_THREADPOOL_WIN32_05_009: [** If there are no errors then this `work_item_context` of type `THREADPOOL_WORK_ITEM_HANDLE` would be returned indicating a succcess to the caller**]**
**S_R_S_THREADPOOL_WIN32_05_010: [** If any error occurs, `threadpool_create_work_item` shall fail, free the newly created context and return a `NULL` value. **]**
### threadpool_schedule_work_item
```c
MOCKABLE_FUNCTION(, int, threadpool_schedule_work_item, THANDLE(THREADPOOL), threadpool, THREADPOOL_WORK_ITEM_HANDLE, work_item_context);
```
`threadpool_schedule_work_item` schedules a work item to be executed by the threadpool.
**S_R_S_THREADPOOL_WIN32_05_011: [** If `threadpool` is NULL, `threadpool_schedule_work_item` shall fail and return a `non-zero` value. **]**
**S_R_S_THREADPOOL_WIN32_05_012: [** If `work_item_context` is NULL, `threadpool_schedule_work_item` shall fail and return a `non-zero` value. **]**
**S_R_S_THREADPOOL_WIN32_05_013: [** `threadpool_schedule_work_item` shall call `SubmitThreadpoolWork` to submit the work item for execution. **]**
### threadpool_destroy_work_item
```c
MOCKABLE_FUNCTION(, void, threadpool_destroy_work_item, THREADPOOL_WORK_ITEM_HANDLE, work_item_context);
```
`threadpool_destroy_work_item` closes the `ptp_work` member variable in `work_item_context`and then frees the `work_item_context`
**S_R_S_THREADPOOL_WIN32_05_014: [** If `work_item_context` is `NULL`, `threadpool_destroy_work_item` shall fail and not do anything before returning. **]**
**S_R_S_THREADPOOL_WIN32_05_015: [** `threadpool_destroy_work_item` shall call `CloseThreadpoolWork` to close `ptp_work`. **]**
**S_R_S_THREADPOOL_WIN32_05_016: [** `threadpool_destroy_work_item` shall free the `work_item_context`. **]**

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

@ -37,6 +37,12 @@ extern "C" {
int real_threadpool_open(THANDLE(THREADPOOL) threadpool);
void real_threadpool_close(THANDLE(THREADPOOL) threadpool);
THREADPOOL_WORK_ITEM_HANDLE real_threadpool_create_work_item(THANDLE(THREADPOOL) threadpool, THREADPOOL_WORK_FUNCTION work_function, void* work_function_context);
int real_threadpool_schedule_work_item(THANDLE(THREADPOOL) threadpool, THREADPOOL_WORK_ITEM_HANDLE work_item_context);
void real_threadpool_destroy_work_item(THREADPOOL_WORK_ITEM_HANDLE work_item_context);
int real_threadpool_schedule_work(THANDLE(THREADPOOL) threadpool, THREADPOOL_WORK_FUNCTION work_function, void* work_function_context);
int real_threadpool_timer_start(THANDLE(THREADPOOL) threadpool, uint32_t start_delay_ms, uint32_t timer_period_ms, THREADPOOL_WORK_FUNCTION work_function, void* work_function_context, TIMER_INSTANCE_HANDLE* timer_handle);

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

@ -5,6 +5,9 @@
#define threadpool_create real_threadpool_create
#define threadpool_open real_threadpool_open
#define threadpool_close real_threadpool_close
#define threadpool_create_work_item real_threadpool_create_work_item
#define threadpool_schedule_work_item real_threadpool_schedule_work_item
#define threadpool_destroy_work_item real_threadpool_destroy_work_item
#define threadpool_schedule_work real_threadpool_schedule_work
#define threadpool_timer_start real_threadpool_timer_start
#define threadpool_timer_restart real_threadpool_timer_restart

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

@ -29,6 +29,13 @@ typedef struct WORK_ITEM_CONTEXT_TAG
void* work_function_context;
} WORK_ITEM_CONTEXT;
typedef struct THREADPOOL_WORK_ITEM_TAG
{
THREADPOOL_WORK_FUNCTION work_function;
void* work_function_context;
PTP_WORK* ptp_work;
} THREADPOOL_WORK_ITEM, *THREADPOOL_WORK_ITEM_HANDLE;
typedef struct TIMER_INSTANCE_TAG
{
PTP_TIMER timer;
@ -78,6 +85,11 @@ static VOID CALLBACK on_work_callback(PTP_CALLBACK_INSTANCE instance, PVOID cont
}
}
static VOID CALLBACK on_work_callback_v2(PTP_CALLBACK_INSTANCE instance, PVOID context, PTP_WORK work)
{
LogWarning("Printing %p %p %p", instance, context, work);
}
static void internal_close(THREADPOOL* threadpool)
{
do
@ -113,7 +125,7 @@ static void threadpool_dispose(THREADPOOL* threadpool)
int32_t current_state = InterlockedCompareExchange(&threadpool->state, THREADPOOL_WIN32_STATE_CLOSING, THREADPOOL_WIN32_STATE_OPEN);
if (current_state == THREADPOOL_WIN32_STATE_OPEN)
{
/* Codes_SRS_THREADPOOL_WIN32_01_007: [ threadpool_destroy shall perform an implicit close if threadpool is OPEN. ]*/
/* Codes_SRS_THREADPOOL_WIN32_01_007: [ threadpool_dispose shall perform an implicit close if threadpool is OPEN. ]*/
internal_close(threadpool);
break;
}
@ -265,6 +277,26 @@ void threadpool_close(THANDLE(THREADPOOL) threadpool)
}
}
THREADPOOL_WORK_ITEM_HANDLE threadpool_create_work_item(THANDLE(THREADPOOL) threadpool, THREADPOOL_WORK_FUNCTION work_function, void* work_function_context)
{
(void*)threadpool;
(void*)work_function;
(void*)work_function_context;
return NULL;
}
int threadpool_schedule_work_item(THANDLE(THREADPOOL) threadpool, THREADPOOL_WORK_ITEM_HANDLE work_item_context)
{
(void*)threadpool;
(void*)work_item_context;
return 0;
}
void threadpool_destroy_work_item(THREADPOOL_WORK_ITEM_HANDLE work_item_context)
{
(void*)work_item_context;
}
int threadpool_schedule_work(THANDLE(THREADPOOL) threadpool, THREADPOOL_WORK_FUNCTION work_function, void* work_function_context)
{
int result;