Устанавливает огонь в boost :: intrusive_ptr при использовании в контейнере - PullRequest
2 голосов
/ 01 апреля 2011

У меня есть договоренность между производителем и потребителем для обработки событий, поступающих из сети.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();
}

После завершения обработки события событие удаляется из очереди.Оставление события в очереди позволяет Диспетчеру проверить элемент в начале очереди, чтобы увидеть, относится ли он к тому, который он пытается выделить.(Сделано защищенным мьютексом способом, но не показано)

Вот код, извлекающий указатель из 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();
    ...
}

Проблема в том, что ASSERT запускается в коде intrusive_ptr, когдаЯ использую заглядывающий указатель.

/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 голосов
/ 01 апреля 2011

Посмотрите на документы intrusive_ptr:

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

Чтобы разыменовать его, он должен содержать ненулевой указатель.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...