I implemented one of these in the latest Class::DBI using Scalar::Utils::weaken(). When an object has been cleaned up, it just looks undefined. My purge code looks like this:
sub purge_dead_from_object_index {
delete @Live_Objects{ grep !defined $Live_Objects{$_}, keys %L
+ive_Object
s };
}