diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b2a0a7..58300ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,12 @@ cmake_minimum_required(VERSION 3.0) -set(CMAKE_C_STANDARD 99) +set(CMAKE_CXX_STANDARD 11) -project(tiny_thread_pool LANGUAGES C) +project(tiny_thread_demo LANGUAGES CXX) -add_executable(tiny_pool main.c tiny_pool.c) -target_link_libraries(tiny_pool pthread) +include_directories(src) + +add_subdirectory(src) + +add_executable(demo demo.cc) +target_link_libraries(demo tiny_pool) diff --git a/demo.cc b/demo.cc new file mode 100644 index 0000000..a053e30 --- /dev/null +++ b/demo.cc @@ -0,0 +1,34 @@ +#include +#include +#include "tiny_pool.h" + +void demo_func(void *arg) { + + std::cout << *(int*)arg << std::endl; + + sleep(1); + +} + +int main() { + std::cout << "tiny thread pool demo start" << std::endl; + + + auto pool = tiny_pool_create(3); + + int dat[] = {0, 1, 2, 3, 4, 5, 6}; + tiny_pool_submit(pool, demo_func, (void*)&dat[0]); + tiny_pool_submit(pool, demo_func, (void*)&dat[1]); + tiny_pool_submit(pool, demo_func, (void*)&dat[2]); + tiny_pool_submit(pool, demo_func, (void*)&dat[3]); + tiny_pool_submit(pool, demo_func, (void*)&dat[4]); + tiny_pool_submit(pool, demo_func, (void*)&dat[5]); + tiny_pool_submit(pool, demo_func, (void*)&dat[6]); + + tiny_pool_boot(pool); + + tiny_pool_join(pool); + + std::cout << "tiny thread pool demo exit" << std::endl; + return 0; +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..f84f5d3 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.0) + +set(CMAKE_C_STANDARD 99) + +project(tiny_thread_pool LANGUAGES C) + +add_library(tiny_pool tiny_pool.c) +target_link_libraries(tiny_pool pthread) diff --git a/tiny_pool.c b/src/tiny_pool.c similarity index 94% rename from tiny_pool.c rename to src/tiny_pool.c index d075cea..97e0d83 100644 --- a/tiny_pool.c +++ b/src/tiny_pool.c @@ -78,6 +78,7 @@ task_t* task_queue_pop(pool_t *pool) { // pop one task with blocking wait pthread_cond_wait(&pool->task_queue_not_empty, &pool->mutex); // wait new task added printf("%lu -> pop exit wait\n", pthread_self()); if (pool->status == EXITING) { + pthread_mutex_unlock(&pool->mutex); printf("%lu -> sub thread exit from idle\n", pthread_self()); pthread_exit(NULL); // sub thread exit at EXITING stage } @@ -190,9 +191,15 @@ void free_tiny_pool(pool_t *pool) { printf("start free pool resource\n"); +// pthread_mutex_unlock(&pool->mutex); + +// printf("flag 1\n"); + pthread_cond_destroy(&pool->without_busy_thread); pthread_cond_destroy(&pool->task_queue_not_empty); pthread_cond_destroy(&pool->task_queue_empty); +// printf("flag 2\n"); + pthread_mutex_destroy(&pool->mutex); free(pool->threads); @@ -202,6 +209,8 @@ void free_tiny_pool(pool_t *pool) { } +#include + bool tiny_pool_join(pool_t *pool) { printf("start pool join\n"); @@ -237,11 +246,26 @@ bool tiny_pool_join(pool_t *pool) { pthread_mutex_unlock(&pool->mutex); // prevent other functions blocking waiting printf("start sub threads joining\n"); + +// for (uint32_t i = 0; i < pool->thread_num; ++i) { +// pthread_cond_broadcast(&pool->task_queue_not_empty); // trigger idle threads +// while (pthread_mutex_trylock(&pool->mutex)) { +// printf("try lock again\n"); +// } +// pthread_mutex_unlock(&pool->mutex); +// } +// +// printf("free threads complete\n"); + for (uint32_t i = 0; i < pool->thread_num; ++i) { pthread_cond_broadcast(&pool->task_queue_not_empty); // trigger idle threads + printf("start join sub thread %lu\n", pool->threads[i]); pthread_join(pool->threads[i], NULL); printf("sub thread %lu joined\n", pool->threads[i]); } + +// sleep(10); + printf("sub threads join complete\n"); free_tiny_pool(pool); diff --git a/tiny_pool.h b/src/tiny_pool.h similarity index 98% rename from tiny_pool.h rename to src/tiny_pool.h index 4ee507c..11b148c 100644 --- a/tiny_pool.h +++ b/src/tiny_pool.h @@ -75,6 +75,10 @@ typedef struct pool_t { pthread_cond_t without_busy_thread; // condition for busy thread number becomes zero } pool_t; +#ifdef __cplusplus +extern "C" { +#endif + /// This function create a new thread pool, you need to specify the number of threads, /// it will be in the `PREPARING` state, and return NULL on failure. pool_t* tiny_pool_create(uint32_t size); @@ -104,4 +108,8 @@ void tiny_pool_detach(pool_t *pool); /// this will cause the interruption of running tasks and the loss of un-running tasks. void tiny_pool_kill(pool_t *pool); +#ifdef __cplusplus +}; +#endif + #endif