在容器中使用时,在boost :: intrusive_ptr中断言

时间:2011-04-01 10:20:26

标签: c++ linux boost

我有一个生产者 - 消费者安排来处理来自网络的事件。 Dispatcher通过工作线程拥有的互斥锁保护队列为多个EventHandler线程提供工作。放置在队列中的事件对象使用boost::intrusive_ptr

class Event { ... }
typedef boost::intrusive_ptr<Event> EventPtr;

队列是定义为的模板:

template<typename Data>
class ConcurrentQueue : boost::noncopyable
{
protected:
    std::queue<Data> _queue;
    boost::mutex _dataMutex;
    boost::condition_variable _dataAvailable;
    ...
public:
    ...
    void push(Data const& data)
    {
        boost::mutex::scoped_lock lock(_dataMutex);
        _queue.push(data);
        lock.unlock();
        _dataAvailable.notify_one();
    }
...
};
...
typedef ConcurrentQueue<EventPtr> EventQueue;

EventHandler等待事件放入其队列,并在可用时使用方法waitAndPop将其从队列中删除:

void waitAndPop(Data& poppedValue)
{
    boost::mutex::scoped_lock lock(_dataMutex);
    while(_queue.empty())
    {
        _dataAvailable.wait(lock);
    }
    poppedValue = _queue.front();
    _queue.pop();
}

这很有效,但我需要确保Dispatcher将相关工作提供给同一个EventHandler。所以我实现了一个waitAndPeek方法,将Event对象留在队列中,但返回指向它的指针。

void waitAndPeek(Data& peekedValue)
{
    boost::mutex::scoped_lock lock(_dataMutex);
    while(_queue.empty())
    {
        _dataAvailable.wait(lock);
    }
    peekedValue = _queue.front();
}

一旦事件进动完成,事件就会从队列中弹出。将事件保留在队列中允许Disptacher检查队列头部的项目,以查看它是否与它尝试分配的项目相关。 (以互斥保护方式完成但未显示)

这是从EventQueue中提取指针的代码:

EventPtr event;
// Loop, processing events placed on the queue.   
while (true)
{
    // Blocking call. Will halt the thread until there is work to do.
    _eventQueue->waitAndPeek(event);
    // Try to access event but ASSERT fires
    int id = event->getId();
    ...
}

问题是当我使用peeked指针时,intrusive_ptr代码中会触发ASSERT。

/usr/local/packages/Boost/1.40.0/include/boost/smart_ptr/intrusive_ptr.hpp:166:
T* boost::intrusive_ptr<T>::operator->() const [with T = Event]:
Assertion `px != 0' failed.

只要我将代码恢复为使用waitAndPop方法,问题就会消失,导致ASSERT触发的原因只是因为我将事件留在了队列中?

1 个答案:

答案 0 :(得分:0)

看看intrusive_ptr docs:

http://www.boost.org/doc/libs/1_46_1/libs/smart_ptr/intrusive_ptr.html#indirection

为了取消引用它,它必须包含一个非NULL指针。