如何管理"shortest of"类型的生命周期?

How to manage lifetime of the type "shortest of"?

本文关键字:类型 生命 周期 of shortest 管理 何管理      更新时间:2023-10-16

当一个对象有一个父对象时,我们使用复合,父对象应该关心对象的生命周期。在同样的情况下,我们使用unique_ptr,但对象可以是nullptr

当几个外部实体可能需要我们的对象时,我们使用shared_ptr,因此它的生命周期被延长,直到最后一个外部实体失去兴趣。

这里我想问另一个生活中的情况。如果对象需要在几个持续时间中最短,该怎么办?

下面是一个例子。让我们有一个一次性计时器,它存储一个函子并在计数完成后执行它。这对我来说是有意义的*,这个计时器对象在:

之后被销毁:
1. fulfilling its task - therefore it should be able to destroy istelf
 or
2. the parent loosing interest in the timer - so the parent should be able to 
     destroy the object as well

目前,我使用唯一指针的笨拙实现。这个问题的一个好的模式/指导方针/实现是什么?

*原因:1)函子可能拥有其他资源2)计时器可能已经设置为一个非常大的数字,然后放弃3)如果父类已经被销毁,我们一般不想调用它的回调

这里存在严重的并发性和重入性问题。

当两个或两个以上的代码都有权删除一个指针时,任何一个代码都不能可靠地解引用该指针,因为在解引用时,另一个代码可能会销毁该指针。

同样地,任何你检查你拥有所有权的分支都可能在任何其他非本地(比如函数调用)运行的时候变得陈旧,即使没有并发性。

我们可以绕过这些。

template<class T>
struct shared_destroyable {
  std::shared_ptr<T> lock() const {
    return atomic_load<T>(ptr.get());
  }
  explicit operator bool() const { return (bool)lock; }
  void reset( std::shared_ptr<T> pin = {} ) {
    atomic_store(ptr.get(), std::move(pin));
  }
  shared_destroyable(std::shared_ptr<T> pin):
    ptr(std::make_shared<std::shared_ptr<T>>(std::move(pin))
  {}
  shared_destroyable()=default;
  shared_destroyable(shared_destroyable&&)=default;
  shared_destroyable(shared_destroyable const&)=default;
  shared_destroyable& operator=(shared_destroyable&&)=default;
  shared_destroyable& operator=(shared_destroyable const&)=default;
private:
  std::shared_ptr<std::shared_ptr<T>> ptr;
};

这表现得像weak_ptr shared_ptr的混合。

如果最后一个消失了,对象被销毁。

然而,如果它们中的任何一个是.reset(),那么只要最后一个具有lock() ed的代码结束了的作用域,该对象就会被销毁

所引用的赋值变化

所以在使用时,你可以这样做:

if(auto sp = sd.lock()) {
  // use sp
}

sp的生命周期保证在{}的范围内持续,即使有人在块内,在另一个线程中,或者当您调用其他一些方法时执行sd.reset()

我认为最好的解决方案是有一个包装器对象,它有一个指向实际计时器对象的唯一指针,以及一个计时器对象的getter,如果它已被销毁,则返回null。

这样,如果计时器过期并被销毁,没有失去兴趣的调用者不会留下一个表面上有效但实际上无效的指向计时器对象的指针。