extend killer-stash to allow registration of custom deleter functions
This commit is contained in:
parent
59145e0f14
commit
cb838ba5b6
2 changed files with 67 additions and 6 deletions
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue