extend killer-stash to allow registration of custom deleter functions

This commit is contained in:
Fischlurch 2010-06-12 03:12:02 +02:00
parent 59145e0f14
commit cb838ba5b6
2 changed files with 67 additions and 6 deletions

View file

@ -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<Killer> Killers;
Killers killers_;
@ -166,13 +169,21 @@ namespace lib {
template<typename TY>
void
manage (void *obj)
manage (void* obj)
{
if (!obj) return;
REQUIRE (!isRegistered (obj));
killers_.push_back (Killer (how_to_kill<TY>, obj));
}
void
manage (void* obj, KillFun* customDeleter)
{
if (!obj) return;
REQUIRE (!isRegistered (obj));
killers_.push_back (Killer (customDeleter, obj));
}
template<typename TY>
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<typename TY>
void
@ -201,11 +212,11 @@ namespace lib {
private:
/** trampoline function to invoke destructor
* of the specific target type */
template<typename TY>
template<typename X>
static void
how_to_kill (void* subject)
{
TY* victim = static_cast<TY*> (subject);
X* victim = static_cast<X*> (subject);
ENSURE (victim);
delete victim;
};

View file

@ -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<Special*> (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);
}
};