From cb838ba5b6bbbcbe1339aad9f02593220d05cf9b Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 12 Jun 2010 03:12:02 +0200 Subject: [PATCH] extend killer-stash to allow registration of custom deleter functions --- src/lib/del-stash.hpp | 23 ++++++++++++----- tests/lib/del-stash-test.cpp | 50 ++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/src/lib/del-stash.hpp b/src/lib/del-stash.hpp index fa3c87eb5..b05725c94 100644 --- a/src/lib/del-stash.hpp +++ b/src/lib/del-stash.hpp @@ -68,13 +68,15 @@ namespace lib { class DelStash : boost::noncopyable { + + typedef void KillFun(void*); + /** - * @internal entry to store target object + * @internal entry to store target pointer * and the actual deleter function to use */ class Killer { - typedef void KillFun(void*); void* target_; KillFun* killIt_; @@ -106,6 +108,7 @@ namespace lib { typedef std::vector Killers; + Killers killers_; @@ -166,13 +169,21 @@ namespace lib { template void - manage (void *obj) + manage (void* obj) { if (!obj) return; REQUIRE (!isRegistered (obj)); killers_.push_back (Killer (how_to_kill, obj)); } + void + manage (void* obj, KillFun* customDeleter) + { + if (!obj) return; + REQUIRE (!isRegistered (obj)); + killers_.push_back (Killer (customDeleter, obj)); + } + template void @@ -180,7 +191,7 @@ namespace lib { { triggerKill (obj); } // note: entry remains in the killer vector, - // but is now disabled and can't be found anymore + // but is disabled and can't be found anymore template void @@ -201,11 +212,11 @@ namespace lib { private: /** trampoline function to invoke destructor * of the specific target type */ - template + template static void how_to_kill (void* subject) { - TY* victim = static_cast (subject); + X* victim = static_cast (subject); ENSURE (victim); delete victim; }; diff --git a/tests/lib/del-stash-test.cpp b/tests/lib/del-stash-test.cpp index 052604823..f09500b98 100644 --- a/tests/lib/del-stash-test.cpp +++ b/tests/lib/del-stash-test.cpp @@ -108,6 +108,7 @@ namespace test{ { checksum = 0; checkSingleKill(); + checkCustomKill(); checkMassKill(); checkAutoKill(); } @@ -205,6 +206,55 @@ namespace test{ CHECK (0 == checksum); } + + + /** @test use a custom-provided + * deleter function + */ + void + checkCustomKill () + { + DelStash killer; + CHECK (0 == killer.size()); + + /** a very specific setup, + * bound to mess up the checksum, + * unless the random bias is removed + * by the custom deleter function + */ + class Special + : Probe<555> + { + char secret_; + + public: + Special() + : Probe<555>() + , secret_('a' + (rand() % (1+'z'-'a'))) + { + checksum += secret_; + } + + static void + selfKill (void *it) + { + Special *self = static_cast (it); + checksum -= self->secret_; + delete self; + } + }; + + + void * type_erased = new Special(); + CHECK (0 < checksum); + + killer.manage (type_erased, &Special::selfKill); + CHECK (1 == killer.size()); + + killer.kill(type_erased); + CHECK (0 == killer.size()); + CHECK (0 == checksum); + } };