如何使用 Boost 库智能指针管理对象生命周期?

发布于 2024-08-07 00:49:30 字数 230 浏览 8 评论 0原文

有一个场景我需要使用shared_ptr和weak_ptr智能指针来解决。

两个线程,线程 1 和线程 2 2、正在使用一个名为 A 的共享对象。每个线程都有对该对象的引用。线程 1 决定删除对象 A,但同时线程 2 可能正在使用它。如果我使用shared_ptr在每个线程中保存对象A的引用,则该对象将不会在正确的时间被删除。

我应该做什么才能在应该删除对象时删除该对象并防止同时使用该对象的其他线程中出现错误?

There is a scenario that i need to solve with shared_ptr and weak_ptr smart pointers.

Two threads, thread 1 & 2, are using a shared object called A. Each of the threads have a reference to that object. thread 1 decides to delete object A but at the same time thread 2 might be using it. If i used shared_ptr to hold object A's references in each thread, the object wont get deleted at the right time.

What should i do to be able to delete the object when its supposed to and prevent an error in other threads that using that object at the same time?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一萌ing 2024-08-14 00:49:30

有两种情况:

一个线程拥有共享数据

如果线程 1 是对象的“所有者”,而线程 2 只需要使用它,则在线程 2 中存储一个weak_ptr。弱指针不参与引用计数,而是提供一种在对象仍然存在的情况下访问对象的shared_ptr 的方法。如果该对象不存在,weak_ptr将返回一个空/空的shared_ptr。

这是一个示例:

  class CThread2
  {
  private:
      boost::weak_ptr<T> weakPtr
  public:
   void SetPointer(boost::shared_ptr<T> ptrToAssign)
   {
        weakPtr = ptrToAssign;
   }

   void UsePointer()
   {
        boost::shared_ptr<T> basePtr;
        basePtr = weakPtr.lock()
        if (basePtr)
        {
             // pointer was not deleted by thread a and still exists,
             // so it can be used.
        }
        else
        {
             // thread1 must have deleted the pointer
        }
   }
  };

我对此问题的回答(链接)也可能有用。

数据确实由两者拥有

如果您的任何一个线程可以执行删除,那么您就不能拥有我上面描述的内容。由于除了底层对象之外,两个线程都需要知道指针的状态,因此在这种情况下“指向指针的指针”可能很有用。

 boost::shared_ptr< boost::shared_ptr<T> >

或(通过原始 ptr)

shared_ptr<T>* sharedObject;

或只是

T** sharedObject;

为什么这有用?

  • 你只有一个 T 的引用者(事实上,shared_ptr 是相当多余的)
  • 两个线程都可以检查单个共享指针的状态(它是 NULL 吗?它是否被另一个线程删除了?)

陷阱:
- 想想当双方尝试同时删除时会发生什么,您可能需要锁定此指针

修订示例:

 class CAThread
  {
  private:
      boost::shared_ptr<T>* sharedMemory;
  public:
   void SetPointer(boost::shared_ptr<T>* ptrToAssign)
   {
        assert(sharedMemory != NULL);
        sharedMemory = ptrToAssign;
   }

   void UsePointer()
   {
        // lock as needed
        if (sharedMemory->get() != NULL)
        {
             // pointer was not deleted by thread a and still exists,
             // so it can be used.
        }
        else
        {
             // other thread must have deleted the pointer
        }
   }

   void AssignToPointer()
   {
        // lock as needed
        sharedMemory->reset(new T);
   }

   void DeletePointer()
   {
        // lock as needed
        sharedMemory->reset();
   }
  };

我忽略了底层数据的所有并发问题,但这并不是您真正要问的。

There's 2 cases:

One thread owns the shared data

If thread1 is the "owner" of the object and thread2 needs to just use it, store a weak_ptr in thread2. Weak pointers do not participate in reference counting, instead they provide a way to access a shared_ptr to the object if the object still exists. If the object doesn't exist, weak_ptr will return an empty/null shared_ptr.

Here's an example:

  class CThread2
  {
  private:
      boost::weak_ptr<T> weakPtr
  public:
   void SetPointer(boost::shared_ptr<T> ptrToAssign)
   {
        weakPtr = ptrToAssign;
   }

   void UsePointer()
   {
        boost::shared_ptr<T> basePtr;
        basePtr = weakPtr.lock()
        if (basePtr)
        {
             // pointer was not deleted by thread a and still exists,
             // so it can be used.
        }
        else
        {
             // thread1 must have deleted the pointer
        }
   }
  };

My answer to this question (link) might also be useful.

The data is truly owned by both

If either of your threads can perform deletion, than you can not have what I describe above. Since both threads need to know the state of the pointer in addition to the underlying object, this may be a case where a "pointer to a pointer" is useful.

 boost::shared_ptr< boost::shared_ptr<T> >

or (via a raw ptr)

shared_ptr<T>* sharedObject;

or just

T** sharedObject;

Why is this useful?

  • You only have one referrer to T (in fact shared_ptr is pretty redundant)
  • Both threads can check the status of the single shared pointer (is it NULL? Was it deleted by the other thread?)

Pitfalls:
- Think about what happens when both sides try to delete at the same time, you may need to lock this pointer

Revised Example:

 class CAThread
  {
  private:
      boost::shared_ptr<T>* sharedMemory;
  public:
   void SetPointer(boost::shared_ptr<T>* ptrToAssign)
   {
        assert(sharedMemory != NULL);
        sharedMemory = ptrToAssign;
   }

   void UsePointer()
   {
        // lock as needed
        if (sharedMemory->get() != NULL)
        {
             // pointer was not deleted by thread a and still exists,
             // so it can be used.
        }
        else
        {
             // other thread must have deleted the pointer
        }
   }

   void AssignToPointer()
   {
        // lock as needed
        sharedMemory->reset(new T);
   }

   void DeletePointer()
   {
        // lock as needed
        sharedMemory->reset();
   }
  };

I'm ignoring all the concurrency issues with the underlying data, but that's not really what you're asking about.

ゞ记忆︶ㄣ 2024-08-14 00:49:30

Qt 有一个 QPointer 类来执行此操作。如果指针所指向的内容被删除,则指针会自动设置为 0。

(当然,只有当您有兴趣将 Qt 集成到您的项目中时,这才有效。)

Qt has a QPointer class that does this. The pointers are automatically set to 0 if what they're pointed at is deleted.

(Of course, this would only work if you're interested in integrating Qt into your project.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文