2011-12-10 40 views
1

我有一個記錄器類與tbb :: concurrent_queue作爲成員字段。使用記錄器對象的線程調用方法將消息推送到此內部隊列中。記錄器有一個內部線程,它正在使用這些消息,直到它收到一個sentinel消息,然後這個內部線程退出。問題是,如果此記錄器對象的客戶端嘗試將更多消息記錄到此記錄器(在關閉的調用發送了標記之後),則消息被傳遞到隊列中,但從未在另一端拾取並無聲無息地丟失。理想情況下,我希望在這種情況下通知,但在退出時使用內部消費者線程設置的標誌來檢查每次將新消息推送到隊列時是否會增加分支開銷,使其成爲我的關鍵路徑。如何在完成生產者消費者隊列時通過交換指針來避免條件代價?

我聽到的一個想法是,可能是消費者線程..在退出之前..有些原子地換出隊列的指針,以便下一個調用它會調用其他可以處理不同消息的東西..

即調用:m_buffer-> push(message)其中m_buffer是一個指向tbb :: concurrent_queue的指針,應該在消費者線程完成後仍然看起來像m_buffer-> push(message),除了它到達其他地方。我的一個自定義處理程序...

但我該怎麼做?我不能交換m_buffer指向任何其他自定義類,除非我從tbb :: concurrent_queue繼承...是否有另一種方法來解決這個問題?

謝謝

回答

1

聽起來更像是一個設計問題給我。記錄器的客戶需要什麼?記錄消息。他們並不關心是否進入隊列,或者寫在屏幕上,或者寫在一張紙上,插入一個玻璃瓶並扔進大海。

所以你的記錄器只需要公開一個log()方法,沒有別的。通過在數組中保持兩個隊列並自動切換指針或索引,內部會發生隊列交換。

另外,如果你的日誌代碼的速度是至關重要的,你可能會做的太多了吧......

+0

是的客戶通話記錄(「嗨」),但該通話嘗試非常異步,內部只是: theQueue-> push(msgObj); 事情是,一旦一個人調用logger.shutdown(),一個哨兵msgObj被引入到Queue中,以便消耗msgObjs的線程知道它已完成......一旦發生這種情況,我希望能夠通知調用者在關機後(他們不應該這樣做),他們的消息沒有得到保存的日誌()(我不想這樣的: if(!consumerDone) theQueue-> push(msgObj); 因爲我一直支付一個分支...因此想知道...... –

+0

所以你認爲這一個分支比推入隊列,切換上下文到另一個線程或寫入磁盤更昂貴?你的表現概念可能有點偏差。 – Thomas

0

爲什麼會記錄線程必須設置「沒有更多的記錄」標誌?記錄器的'shutdown'方法應該設置它,以防止在它發出最終將信號線程關閉的標記之前排隊的更多消息,以便標記始終是排隊的最後一個項目。記錄請求在設置標誌時做什麼取決於記錄器。

+0

是的,我想阻止更多的消息從哨兵後排隊。但我不想支付全部分支的費用,如: if(stillLogging) theQueue-> push(message); 所以對log()的調用盡可能快。有沒有辦法讓接收標記的線程以某種方式移動東西,只需要按照以下方式移動東西:theQueue-> push(message);在調用log()時,會突然做一些不同於關閉之後消息的正常排隊的東西...因爲可能交換了Queue指向的東西(它當前是tbb :: concurrent_queue ; ? –