0

请注意 - 这些构建适用于 VS2008/VS2010 构建,我不能使用任何 11 个构造。

想象一下,我有订阅者在听某个发布者。我的发布者有一个订阅者指针容器。在我的 void detach(ISubscriber *) 中,我不会锁定订阅者列表,而是将指针“NULL”出来,因为没有更好的词,对于那个订阅者。

//My container in the publisher.  Inserts to not invalidate, removals only invalidate iterators pointing to the removed element, for this reason we NULL
Container<ISubscriber *> myContainer;

Now in the publisher...
void NotifySubscribers(){
   foreach(subscriber in container){
      if(subscriber)//This is my problem
         subscriber->notify()
   }
}

第 3 行 - 测试指针并指向有效对象。在执行第 4 行之前,另一个线程将订阅者设为 NULL。第 4 行 - 繁荣。

我的问题,有没有一种方法可以使用某种互锁的东西,使测试和调用是原子的。

例如,对于析构函数中的引用计数对象,类似这样的工作

 RefCountObject::~RefCountObject(){
    if(InterlockedDecrement(&m_count) == 0)
      delete m_data;
 }

在这里,参考计数器自动递减并针对零进行测试,然后只有当等于零时,才会释放数据。

有没有办法让我根据指针的有效性来调用函数?

编辑1:我需要根据评论澄清一点,并感谢您的回复。发布者不负责订阅者的“内存释放”,因此不会有泄漏。在通知之后,发布者将通过一个循环,通过删除无效的订阅者来清理容器。

现在至于订阅者自己。当他们分离时,他们只是从听发布者分离。它们本身将存在于静态对象中(这是我们需要的合同)。为什么?因为我们不能在通知期间持有锁。唯一的其他选择是使用 Share_Ptr,由于未来的版本控制,决定不将其合并到此 DLL 中。

我创建了一个手写的 shared_ptr,但后来我突然想到,任何对未包含在资源管理类中的对象的引用都会落入同样的陷阱,只是推动订阅者必须确保不这样做的“要求”引用在其实现所述订阅者中的任何悬空引用。

这让我们回到刚才的说法,订阅者不能被“释放”,目前所有将使用它的客户端都是静态对象。我们只是在展望未来。一些用户是遗留应用程序,不容易引入 enabled_shared_from_this 等。

4

2 回答 2

3

有没有办法我可以使用某种互锁的东西,使测试和调用是原子的。

对于测试,是的,会有办法。你只想比较一个指针。

打电话,我怀疑。您将需要一个守卫在呼叫周围,即关键部分。

于 2012-09-17T21:14:30.623 回答
0

您可以使用“智能指针”策略对指针进行延迟归零。只要有人引用了指针,由互锁引用计数确定,就保持指针有效;当计数变为零时,它是安全的。

于 2012-09-17T23:40:41.870 回答