2011-04-01 72 views
2

我有一個Producer-Consumer安排來處理來自網絡的事件。 A Dispatcher通過工作線程擁有的互斥鎖保護隊列向多個EventHandler線程提供工作。放置在隊列中的事件對象使用boost::intrusive_ptr在容器中使用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(); 
    ... 
} 

的問題是一個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只是火碼?

回答

0

看intrusive_ptr文檔:

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

爲了取消對它的引用,它必須持有非NULL指針。

+0

當我使用彈出方法刪除它時,隊列上的'Event'對象是非空的。當我將對象留在隊列中並嘗試使用'peek'返回的指針時,麻煩就開始了。就好像ref count正在遞減,即使我有一個指向對象的指針。我添加了對象使用計數的記錄,以便在增量/減量時追蹤它。 – Tony 2011-04-01 12:43:13

+0

我接受你的答案,因爲事實證明,我試圖使用的事件已被刪除,所以你在說「......它必須保存一個非NULL指針」時是正確的。 問題與增強庫或集合中intrusive_ptr的使用無關。令人尷尬的是,這是由於在某些情況下在當前任務出現問題時清除了工作隊列的功能。我仍然在隊列頭部有一個指向事件的指針(現在被刪除),所以代碼使用了一個已刪除的指針並拋出了斷言。 – Tony 2011-04-12 08:54:32