dougm 01/04/29 21:35:09 Added: src/modules/perl modperl_global.c modperl_global.h Log: module to manage globals and tls Revision Changes Path 1.1 modperl-2.0/src/modules/perl/modperl_global.c Index: modperl_global.c =================================================================== #include "mod_perl.h" void modperl_global_request_cfg_set(request_rec *r) { MP_dDCFG; MP_dRCFG; /* only if PerlOptions +GlobalRequest and not done already */ if (MpDirGLOBAL_REQUEST(dcfg) && !MpReqSET_GLOBAL_REQUEST(rcfg)) { modperl_global_request_set(r); MpReqSET_GLOBAL_REQUEST_On(rcfg); } } void modperl_global_request_set(request_rec *r) { MP_dRCFG; modperl_tls_set_request_rec(r); /* so 'PerlOptions +GlobalRequest' doesnt wipe us out */ MpReqSET_GLOBAL_REQUEST_On(rcfg); if (r->main) { /* reset after subrequests */ modperl_tls_reset_cleanup_request_rec(r->pool, r->main); } } void modperl_global_request_obj_set(pTHX_ SV *svr) { /* XXX: support sublassing */ request_rec *r = modperl_sv2request_rec(aTHX_ svr); modperl_global_request_set(r); } #if MP_THREADED static apr_status_t modperl_global_cleanup(void *data) { modperl_global_t *global = (modperl_global_t *)data; MP_TRACE_g(MP_FUNC, "destroy lock for %s\n", global->name); MUTEX_DESTROY(&global->glock); return APR_SUCCESS; } #endif void modperl_global_init(modperl_global_t *global, apr_pool_t *p, void *data, const char *name) { Zero(global, 1, modperl_global_t); global->data = data; global->name = name; #if MP_THREADED MUTEX_INIT(&global->glock); apr_pool_cleanup_register(p, (void *)global, modperl_global_cleanup, apr_pool_cleanup_null); #endif MP_TRACE_g(MP_FUNC, "init %s\n", name); } void modperl_global_lock(modperl_global_t *global) { #if MP_THREADED MP_TRACE_g(MP_FUNC, "locking %s\n", global->name); MUTEX_LOCK(&global->glock); #endif } void modperl_global_unlock(modperl_global_t *global) { #if MP_THREADED MP_TRACE_g(MP_FUNC, "unlocking %s\n", global->name); MUTEX_UNLOCK(&global->glock); #endif } void *modperl_global_get(modperl_global_t *global) { return global->data; } void modperl_global_set(modperl_global_t *global, void *data) { global->data = data; } /* hopefully there wont be many of these */ #define MP_GLOBAL_IMPL(gname, type) \ \ static modperl_global_t MP_global_##gname; \ \ void modperl_global_init_##gname(apr_pool_t *p, \ type gname) \ { \ modperl_global_init(&MP_global_##gname, p, \ (void *)gname, #gname); \ } \ \ void modperl_global_lock_##gname(void) \ { \ modperl_global_lock(&MP_global_##gname); \ } \ \ void modperl_global_unlock_##gname(void) \ { \ modperl_global_unlock(&MP_global_##gname); \ } \ \ type modperl_global_get_##gname(void) \ { \ return (type ) \ modperl_global_get(&MP_global_##gname); \ } \ \ void modperl_global_set_##gname(void *data) \ { \ modperl_global_set(&MP_global_##gname, data); \ } \ MP_GLOBAL_IMPL(pconf, apr_pool_t *); #if MP_THREADED static apr_status_t modperl_tls_cleanup(void *data) { return apr_threadkey_private_delete((apr_threadkey_t *)data); } #endif apr_status_t modperl_tls_create(apr_pool_t *p, modperl_tls_t **key) { #if MP_THREADED apr_status_t status = apr_threadkey_private_create(key, NULL, p); apr_pool_cleanup_register(p, (void *)*key, modperl_tls_cleanup, apr_pool_cleanup_null); return status; #else *key = apr_pcalloc(p, sizeof(**key)); return APR_SUCCESS; #endif } apr_status_t modperl_tls_get(modperl_tls_t *key, void **data) { #if MP_THREADED return apr_threadkey_private_get(data, key); #else *data = modperl_global_get(key); return APR_SUCCESS; #endif } apr_status_t modperl_tls_set(modperl_tls_t *key, void *data) { #if MP_THREADED return apr_threadkey_private_set(data, key); #else return APR_SUCCESS; #endif } typedef struct { modperl_tls_t *key; void *data; } modperl_tls_cleanup_data_t; static apr_status_t modperl_tls_reset(void *data) { modperl_tls_cleanup_data_t *cdata; return modperl_tls_set(cdata->key, data); } void modperl_tls_reset_cleanup(apr_pool_t *p, modperl_tls_t *key, void *data) { modperl_tls_cleanup_data_t *cdata = (modperl_tls_cleanup_data_t *)apr_pcalloc(p, sizeof(*cdata)); apr_pool_cleanup_register(p, (void *)cdata, modperl_tls_reset, apr_pool_cleanup_null); } /* hopefully there wont be many of these either */ #define MP_TLS_IMPL(gname, type) \ \ static modperl_tls_t *MP_tls_##gname; \ \ apr_status_t \ modperl_tls_create_##gname(apr_pool_t *p) \ { \ return modperl_tls_create(p, &MP_tls_##gname); \ } \ \ apr_status_t modperl_tls_get_##gname(type *data) \ { \ void *ptr; \ apr_status_t status = \ modperl_tls_get(MP_tls_##gname, &ptr); \ *data = (type )ptr; \ return status; \ } \ \ apr_status_t modperl_tls_set_##gname(void *data) \ { \ return modperl_tls_set(MP_tls_##gname, data); \ } \ \ void modperl_tls_reset_cleanup_##gname(apr_pool_t *p, \ type data) \ { \ modperl_tls_reset_cleanup(p, MP_tls_##gname, \ (void *)data); \ } MP_TLS_IMPL(request_rec, request_rec *); 1.1 modperl-2.0/src/modules/perl/modperl_global.h Index: modperl_global.h =================================================================== #ifndef MODPERL_GLOBAL_H #define MODPERL_GLOBAL_H typedef struct { perl_mutex glock; int flags; void *data; const char *name; } modperl_global_t; #if MP_THREADED typedef apr_threadkey_t modperl_tls_t; #else typedef modperl_global_t modperl_tls_t; #endif void modperl_global_request_cfg_set(request_rec *r); void modperl_global_request_set(request_rec *r); void modperl_global_request_obj_set(pTHX_ SV *svr); void modperl_global_init(modperl_global_t *global, apr_pool_t *p, void *data, const char *name); void modperl_global_lock(modperl_global_t *global); void modperl_global_unlock(modperl_global_t *global); void *modperl_global_get(modperl_global_t *global); void modperl_global_set(modperl_global_t *global, void *data); #define MP_GLOBAL_DECL(gname, type) \ void modperl_global_init_##gname(apr_pool_t *p, type gname); \ void modperl_global_lock_##gname(void); \ void modperl_global_unlock_##gname(void); \ type modperl_global_get_##gname(void); \ void modperl_global_set_##gname(void *) MP_GLOBAL_DECL(pconf, apr_pool_t *); apr_status_t modperl_tls_create(apr_pool_t *p, modperl_tls_t **key); apr_status_t modperl_tls_get(modperl_tls_t *key, void **data); apr_status_t modperl_tls_set(modperl_tls_t *key, void *data); void modperl_tls_reset_cleanup(apr_pool_t *p, modperl_tls_t *key, void *data); #define MP_TLS_DECL(gname, type) \ apr_status_t modperl_tls_create_##gname(apr_pool_t *p); \ apr_status_t modperl_tls_get_##gname(type *data); \ apr_status_t modperl_tls_set_##gname(void *data); \ void modperl_tls_reset_cleanup_##gname(apr_pool_t *p, type data) MP_TLS_DECL(request_rec, request_rec *); #endif /* MODPERL_GLOBAL_H */