APR connects thread pool threads when using apr_thread_pool_schedule
gcc 4.7.2
c89
apr utility 1.4
Hello,
I am using thread pool to start threads. However, I don't see any apr function that allows me to wait for threads to join.
Sippet code, removed all error checks and irrelevant parts:
int main(void)
{
/* Initialize apr internal structures */
apr_initialize();
/* Create memory pool */
rv = apr_pool_create(&mem_pool, NULL);
/* Create thread pool */
memset(&buf, 0, sizeof buf);
rv = apr_thread_pool_create(&thd_pool,
init_threads,
max_threads,
mem_pool);
/* Process the number of jobs */
#define NUMBER_JOBS 1
for(i = 0; i < NUMBER_JOBS; i++) {
rv = apr_thread_pool_schedule(thd_pool,
timeout_duration,
(void*)channel,
(apr_interval_time_t)flash_timeout,
NULL);
}
/*
* Join all threads here
*/
/* Destroy resources */
apr_thread_pool_destroy(thd_pool);
apr_pool_destroy(mem_pool);
apr_terminate();
return 0;
error:
apr_thread_pool_destroy(thd_pool);
apr_pool_destroy(mem_pool);
apr_terminate();
return 1;
}
void* timeout_duration(apr_thread_t *thd, void *data)
{
channel_t *channel = (channel_t*)data;
LOG_DEBUG("Channel timeout notification [ %zu ]", channel->id);
}
I couldn't see any apr utity functions that attach streams.
However I found this function apr_thread_join(apr_status_t *retval, apr_thread_t *thd)
However, it takes as an argument apr_thread_t
.
The timeout_duration function takes on a value apr_thread_t
, but how do I manage to pass it back if I need to use it to connect?
Just a question side of the issue. Are there any sample projects that use apr and I can link. The documentation is very limited.
Thanks a lot for any suggestions,
source to share
Short anser
You don't need to join threads in the thread pool. When you call apr_thread_pool_destroy
, the function will block until all threads have finished their current task.
First answer your last question: I didn't find an example, but libapr and libapr-util are open-source, you can read the source and this is what I did: (I checked SVN-trunk here rev 1441871)
Long answer
Interesting files:
Check first apr_thread_pool.c:394
. This is where we find the implementation apr_thread_pool_destroy
. We can see that it calls a function named apr_pool_cleanup_run
with three arguments, one of which is the pool store, one is the thread-pool-context, and the last is a function pointer thread_pool_cleanup
.
If we follow along apr_pool_cleanup_run
, we go to apr_pools.c:2453
and see what gets called apr_pool_cleanup_kill
. Reading this last function shows us that here in multiple loops over elements (streams) it is cleared (which we will see later) by calling the cleanup_fn
-function argument .
The apr_pool_cleanup_run
final call now appears in the function cleanup_fn
.
The real action goes to the function pointer passed to apr_pool_cleanup_run
. So, back to apr_thread_pool.c:329
find the function thread_pool_cleanup
.
In it, the context variable is terminated
set to 1 and then the function "sleeps" until _myself->thd_cnt
it becomes 0.
Looking for a use, terminated
we find ourselves breaking thread_pool_func
out of the loop when terminated
not zero. It turns out to be thread_pool_func
a function that every thread in the threadpool uses. In a loop, the task is retrieved and executed. When the loop is finished (since it has terminated
become 1), the following code is executed:
/* idle thread been asked to stop, will be joined */
--me->thd_cnt;
This will eventually lead to thd_cnt == 0, which is the condition for the loop to end in thread_pool_cleanup
.
When you call apr_thread_pool_destroy
, all threads are terminated before the function returns.
source to share