geoff 2003/09/09 10:22:39
Modified: t/response/TestAPR pool.pm
xs/APR/Pool APR__Pool.h
xs/maps apr_functions.map
xs/tables/current/ModPerl FunctionTable.pm
Log:
APR::Pool::DESTROY implemented
Reviewed by: stas
Revision Changes Path
1.5 +58 -7 modperl-2.0/t/response/TestAPR/pool.pm
Index: pool.pm
===================================================================
RCS file: /home/cvs/modperl-2.0/t/response/TestAPR/pool.pm,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- pool.pm 5 Sep 2003 16:30:45 -0000 1.4
+++ pool.pm 9 Sep 2003 17:22:39 -0000 1.5
@@ -5,19 +5,28 @@
use Apache::Test;
+use Apache::RequestRec ();
use APR::Pool ();
+use APR::Table ();
use Apache::Const -compile => 'OK';
-sub cleanup {
+sub add_cleanup {
my $arg = shift;
- ok $arg == 33;
+ $arg->[0]->notes->add(cleanup => $arg->[1]);
+ 1;
+}
+
+sub set_cleanup {
+ my $arg = shift;
+ $arg->[0]->notes->set(cleanup => $arg->[1]);
+ 1;
}
sub handler {
my $r = shift;
- plan $r, tests => 4;
+ plan $r, tests => 13;
my $p = APR::Pool->new;
@@ -31,12 +40,54 @@
# my $num_bytes = $p->num_bytes;
# ok $num_bytes;
- $p->cleanup_register(\&cleanup, 33);
- $subp->cleanup_register(\&cleanup, 33);
+ $p->cleanup_register(\&add_cleanup, [$r, 'parent']);
+ $subp->cleanup_register(\&set_cleanup, [$r, 'child']);
- # should destroy the subpool too, so
- # cleanup is called twice
+ # should destroy the subpool too
$p->destroy;
+
+ my @notes = $r->notes->get('cleanup');
+ ok $notes[0] eq 'child';
+ ok $notes[1] eq 'parent';
+ ok @notes == 2;
+
+ # explicity DESTROY the objects
+ my $p2 = APR::Pool->new;
+ $p2->cleanup_register(\&set_cleanup, [$r, 'new DESTROY']);
+ $p2->DESTROY;
+
+ @notes = $r->notes->get('cleanup');
+ ok $notes[0] eq 'new DESTROY';
+ ok @notes == 1;
+
+ # DESTROY should be a no-op on native pools
+ my $p3 = $r->pool;
+ $p3->cleanup_register(\&set_cleanup, [$r, 'native DESTROY']);
+ $p3->DESTROY;
+
+ @notes = $r->notes->get('cleanup');
+ ok $notes[0] eq 'new DESTROY'; # same as before - no change
+ ok @notes == 1;
+
+ # make sure lexical scoping destroys the pool
+ {
+ my $p4 = APR::Pool->new;
+ $p4->cleanup_register(\&set_cleanup, [$r, 'new scoped']);
+ }
+
+ @notes = $r->notes->get('cleanup');
+ ok $notes[0] eq 'new scoped';
+ ok @notes == 1;
+
+ # but doesn't affect native pools
+ {
+ my $p5 = $r->pool;
+ $p5->cleanup_register(\&set_cleanup, [$r, 'native scoped']);
+ }
+
+ @notes = $r->notes->get('cleanup');
+ ok $notes[0] eq 'new scoped'; # same as before - no change
+ ok @notes == 1;
Apache::OK;
}
1.6 +49 -4 modperl-2.0/xs/APR/Pool/APR__Pool.h
Index: APR__Pool.h
===================================================================
RCS file: /home/cvs/modperl-2.0/xs/APR/Pool/APR__Pool.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- APR__Pool.h 13 Jun 2002 02:59:05 -0000 1.5
+++ APR__Pool.h 9 Sep 2003 17:22:39 -0000 1.6
@@ -1,11 +1,22 @@
-#define apr_pool_DESTROY(p) apr_pool_destroy(p)
+#define MP_APR_POOL_NEW "APR::Pool::new"
+/**
+ * create a new pool or subpool
+ * @param obj an APR::Pool object or NULL
+ * @return a new pool or subpool
+ */
static MP_INLINE apr_pool_t *mpxs_apr_pool_create(pTHX_ SV *obj)
{
apr_pool_t *parent = mpxs_sv_object_deref(obj, apr_pool_t);
- apr_pool_t *retval = NULL;
- (void)apr_pool_create(&retval, parent);
- return retval;
+ apr_pool_t *newpool = NULL;
+ (void)apr_pool_create(&newpool, parent);
+
+ /* mark the pool as being created via APR::Pool->new()
+ * see mpxs_apr_pool_DESTROY */
+ apr_pool_userdata_set((const void *)1, MP_APR_POOL_NEW,
+ apr_pool_cleanup_null, newpool);
+
+ return newpool;
}
typedef struct {
@@ -18,6 +29,10 @@
#endif
} mpxs_cleanup_t;
+/**
+ * callback wrapper for Perl cleanup subroutines
+ * @param data internal storage
+ */
static apr_status_t mpxs_cleanup_run(void *data)
{
int count;
@@ -66,6 +81,12 @@
return status;
}
+/**
+ * run registered cleanups
+ * @param p pool with which to associate the cleanup
+ * @param cv subroutine reference to run
+ * @param arg optional argument to pass to the subroutine
+ */
static MP_INLINE void mpxs_apr_pool_cleanup_register(pTHX_ apr_pool_t *p,
SV *cv, SV *arg)
{
@@ -88,4 +109,28 @@
apr_pool_cleanup_register(p, data,
mpxs_cleanup_run,
apr_pool_cleanup_null);
+}
+
+/**
+ * destroy a pool
+ * @param obj an APR::Pool object
+ */
+static MP_INLINE void mpxs_apr_pool_DESTROY(pTHX_ SV *obj) {
+
+ void *flag;
+ apr_pool_t *p;
+
+ /* APR::Pool::DESTROY
+ * we only want to call DESTROY on objects created by
+ * APR::Pool->new(), not objects representing native pools
+ * like r->pool. native pools can be destroyed using
+ * apr_pool_destroy ($p->destroy) */
+
+ p = mpxs_sv_object_deref(obj, apr_pool_t);
+
+ apr_pool_userdata_get(&flag, MP_APR_POOL_NEW, p);
+
+ if (flag) {
+ apr_pool_destroy(p);
+ }
}
1.58 +1 -0 modperl-2.0/xs/maps/apr_functions.map
Index: apr_functions.map
===================================================================
RCS file: /home/cvs/modperl-2.0/xs/maps/apr_functions.map,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -r1.57 -r1.58
--- apr_functions.map 4 Sep 2003 16:39:44 -0000 1.57
+++ apr_functions.map 9 Sep 2003 17:22:39 -0000 1.58
@@ -155,6 +155,7 @@
apr_pool_clear
>apr_pool_clear_debug
apr_pool_destroy
+ DEFINE_DESTROY | mpxs_apr_pool_DESTROY | SV *:obj
>apr_pool_destroy_debug
apr_pool_t *:DEFINE_new | mpxs_apr_pool_create | SV *:obj
-apr_pool_create_ex
1.122 +14 -0 modperl-2.0/xs/tables/current/ModPerl/FunctionTable.pm
Index: FunctionTable.pm
===================================================================
RCS file: /home/cvs/modperl-2.0/xs/tables/current/ModPerl/FunctionTable.pm,v
retrieving revision 1.121
retrieving revision 1.122
diff -u -r1.121 -r1.122
--- FunctionTable.pm 30 Aug 2003 02:33:26 -0000 1.121
+++ FunctionTable.pm 9 Sep 2003 17:22:39 -0000 1.122
@@ -6429,6 +6429,20 @@
]
},
{
+ 'return_type' => 'void',
+ 'name' => 'mpxs_apr_pool_DESTROY',
+ 'attr' => [
+ 'static',
+ '__inline__'
+ ],
+ 'args' => [
+ {
+ 'type' => 'SV *',
+ 'name' => 'obj'
+ },
+ ]
+ },
+ {
'return_type' => 'apr_pool_t *',
'name' => 'mpxs_apr_pool_create',
'attr' => [