用API模拟“std::shared_ptr”的智能指针,将回调绑定到refcount-modifying事件,例如re

Smart pointer analog of `std::shared_ptr` with API to bind callbacks to refcount-modifying events e.g. release/retain … is this a thing?

本文关键字:回调 re 绑定 事件 refcount-modifying 指针 例如 std 模拟 API shared      更新时间:2023-10-16

我需要一个类似于std::shared_ptr的智能接口结构,它为我提供了某种带有暴露钩子的API,可以将refcount-modifying事件(如release/retain,也就是refcout incremental/device)的回调绑定到该API。

我要么想自己实现,要么使用现成的东西,如果它存在的话。

比如,我希望在定义这个假定的shared_ptr式智能指针时,能够最好地说"每当你增加refcount时调用这个可调用函数[但当递减时调用那个可调用函数]"(就像在shared_ptrunique_ptr定义中分别使用delete表达式和deleter函子一样)。


EDIT(来自我下面的评论)-这就是我想要这个的原因:我目前有一个Image类模板,它的核心是一个std::shared_ptr,它包含一个(可能很大的)连续堆分配的内存块。Image具有实现超实验室迭代器的内部类(例如,暴露颜色平面、CBIR哈希数据&c),这些迭代器使用std::weak_ptr来引用所属Image实例的内存块。我想为特定的refcount运行时扩展Image,例如Python c-api,并且与现有的std::shared_ptr refcounter设备绑定比保持两个不同的系统同步更可取。

shared_ptr的默认实现具有共享对象的shared_ptr,所有对象都指向所谓的控制块。正是这个控制块保存了引用计数器,因此是可以更自然地对引用计数变化做出反应的对象。

但如果你真的想通过智能指针来完成,以下可能会起作用:

using std::shared_ptr;
template<class T> class sharedX_ptr;
// the type of function to call when a refcount change happens
template<class T>
void inc_callback(const sharedX_ptr<T>& p)
{
  std::cout << "Increasing refcount via " << &p
            << ", for object: " << p.get() << ", use_count: " << p.use_count()
            << std::endl;
}
template<class T>
void dec_callback(const sharedX_ptr<T>& p)
{
  std::cout << "About to decrease refcount via " << &p
            << ", for object: " << p.get() << ", use_count: " << p.use_count()
            << std::endl;
}
template<class T>
class sharedX_ptr : public shared_ptr<T>
{
  typedef void (*callback)(const sharedX_ptr<T>&);
  callback inc, dec;
public:
  typedef shared_ptr<T> base;
  sharedX_ptr(const sharedX_ptr& p) : base(p), inc(p.inc), dec(p.dec)
  { if (this->get()) inc(*this); }
  template<class U>
  sharedX_ptr(sharedX_ptr<U>&& p) : base(std::move(p)), inc(p.inc), dec(p.dec)
  { /*if (this->get()) inc(*this);*/ }
  template<class U>
  sharedX_ptr(shared_ptr<U> p, callback i = inc_callback<T>, callback d = dec_callback<T>)
    : shared_ptr<T>(std::move(p)), inc(i), dec(d)
    { if (this->get()) inc(*this); }
  sharedX_ptr& operator=(sharedX_ptr&& p) {
    if (this != &p) {
      if (this->get()) dec(*this);
      base::operator=(std::move(p)); inc = p.inc; dec = p.dec;
      /* if (this->get()) inc(*this); */
    }
    return *this;
  }
  template<class U>
  sharedX_ptr& operator=(const sharedX_ptr& p) {
    if (this != &p) {
      if (this->get()) dec(*this);
      base::operator=(p); inc = p.inc; dec = p.dec;
      if (this->get()) inc(*this);
    }
    return *this;
  }
  void reset() { if (this->get()) dec(*this); shared_ptr<T>::reset();}
  ~sharedX_ptr() { if (this->get()) dec(*this); }
};