dougm 00/05/23 13:53:38
Added: src/modules/perl modperl_tipool.c modperl_tipool.h
Log:
"thread item pool" - generic logic broken out from modperl_interp.c so it can be
reused for other things, e.g. database connection handles
Revision ChangesPath
1.1 modperl-2.0/src/modules/perl/modperl_tipool.c
Index: modperl_tipool.c
===
#ifdef USE_ITHREADS
#include "mod_perl.h"
/*
* tipool == "thread item pool"
* this module is intended to provide generic stuctures/functions
* for managing a "pool" of a given items (data structures) within a threaded
* process. at the moment, mod_perl uses this module to manage a pool
* of PerlInterpreter objects. it should be quite easy to reuse for
* other data, such as database connection handles and the like.
* while it is "generic" it is also tuned for Apache, making use of
* ap_pool_t and the like, and implementing start/max/{min,max}_spare/
* max_requests configuration.
* this is another "proof-of-concept", plenty of room for improvement here
*/
modperl_list_t *modperl_list_new(ap_pool_t *p)
{
modperl_list_t *listp =
(modperl_list_t *)ap_pcalloc(p, sizeof(*listp));
return listp;
}
modperl_list_t *modperl_list_last(modperl_list_t *list)
{
while (list->next) {
list = list->next;
}
return list;
}
modperl_list_t *modperl_list_first(modperl_list_t *list)
{
while (list->prev) {
list = list->prev;
}
return list;
}
modperl_list_t *modperl_list_append(modperl_list_t *list,
modperl_list_t *new_list)
{
modperl_list_t *last;
new_list->prev = new_list->next = NULL;
if (!list) {
return new_list;
}
last = modperl_list_last(list);
last->next = new_list;
new_list->prev = last;
return list;
}
modperl_list_t *modperl_list_prepend(modperl_list_t *list,
modperl_list_t *new_list)
{
new_list->prev = new_list->next = NULL;
if (!list) {
return new_list;
}
if (list->prev) {
list->prev->next = new_list;
new_list->prev = list->prev;
}
list->prev = new_list;
new_list->next = list;
return new_list;
}
modperl_list_t *modperl_list_remove(modperl_list_t *list,
modperl_list_t *rlist)
{
modperl_list_t *tmp = list;
while (tmp) {
if (tmp != rlist) {
tmp = tmp->next;
}
else {
if (tmp->prev) {
tmp->prev->next = tmp->next;
}
if (tmp->next) {
tmp->next->prev = tmp->prev;
}
if (list == tmp) {
list = list->next;
}
break;
}
}
#ifdef MP_TRACE
if (!tmp) {
/* should never happen */
MP_TRACE_i(MP_FUNC, "failed to find 0x%lx in list 0x%lx\n",
(unsigned long)rlist, (unsigned long)list);
}
#endif
return list;
}
modperl_list_t *modperl_list_remove_data(modperl_list_t *list,
void *data,
modperl_list_t **listp)
{
modperl_list_t *tmp = list;
while (tmp) {
if (tmp->data != data) {
tmp = tmp->next;
}
else {
*listp = tmp;
if (tmp->prev) {
tmp->prev->next = tmp->next;
}
if (tmp->next) {
tmp->next->prev = tmp->prev;
}
if (list == tmp) {
list = list->next;
}
break;
}
}
return list;
}
modperl_tipool_t *modperl_tipool_new(ap_pool_t *p,
modperl_tipool_config_t *cfg,
modperl_tipool_vtbl_t *func,
void *data)
{
modperl_tipool_t *tipool =
(modperl_tipool_t *)ap_pcalloc(p, sizeof(*tipool));
tipool->ap_pool = p;
tipool->cfg = cfg;
tipool->func = func;
tipool->data = data;
MUTEX_INIT(&tipool->tiplock);
COND_INIT(&tipool->available);
return tipool;
}
void modperl_tipool_init(modperl_tipool_t *tipool)
{
int i;
for (i=0; icfg->start; i++) {
void *item =
(*tipool->func->tipool_sgrow)(tipool, tipool->data);
modperl_tipool_add(tipool, item);
}
MP_TRACE_i(MP_FUNC, "start=%d, max=%d, min_spare=%d, max_spare=%d\n",
tipool->cfg->start, tipool->cfg->max,
ti