vendredi 5 août 2022

How to compute hash of aliased std::weak_ptr?

Assuming a custom HashableWeakPointer as proposed in this question I would like to ask for further clarification of statements written in an answer to that question.

template<class T>
struct HashableWeakPointer {
  // weak ptr API clone goes here.  lock() etc.

  // different ctor:
  HashableWeakPointer (std::shared_ptr<T>const& sp){
    if(!sp) return;
    ptr=sp;
    hash = std::hash<T*>{}(sp.get());
  }
  std::size_t getHash()const{return hash;}
  friend bool operator<(HashableWeakPointer const& lhs, HashableWeakPointer const& rhs){
    return lhs.owner_before(rhs);
  }
  friend bool operator!=(HashableWeakPointer const& lhs, HashableWeakPointer const& rhs){
    return lhs<rhs || rhs<lhs;
  }
  friend bool operator==(HashableWeakPointer const& lhs, HashableWeakPointer const& rhs){
    return !(lhs!=rhs);
  }
private:
  std::weak_ptr<T> ptr;
  std::size_t hash=0;
};
  1. "While a recycled object pointer results in a hash collision, so long as they don't share control blocks they won't be equal."

And as the control block of a weak_ptr is not freed until the last referencing weak_ptr [and shared_ptr...] to that instance is destroyed, this should be save with regard to the cited statement - right?

  1. "One warning: Use of aliasing constructor could result in pathological results. As equality is based on control block equality, not pointer value."

But this is not a deficiency of your proposed solution, but rather a question of one's definition of what it means for two weak_ptrs to be equal, isn't it?

Would the following distinguish aliasing smart pointers with somewhat less pathological results?

friend bool operator<(HashableWeakPointer const& lhs, HashableWeakPointer const& rhs)
{
    return lhs.owner_before(rhs) || ((not rhs.owner_before(lhs)) && (lhs.hash < rhs.hash));
}

where the second part is only evaluated if the first is false, which thus would mean for (lhs.hash < rhs.hash) being relevant it must (not lhs.owner_before(rhs)) && ((not rhs.owner_before(lhs)) evaluate to true, i.e. the same owner be referenced?

Aucun commentaire:

Enregistrer un commentaire