2012-03-13 56 views
0

項目:典型的聊天程序。服務器必須接收來自多個客戶端的文本,並將每個輸入扇出給所有客戶端這是shared_ptr的合適用法嗎?

在服務器中,我希望每個客戶端都有一個包含套接字fd和std ::隊列的結構。每個結構將在std :: list上。

當從客戶端套接字接收到輸入時,我想遍歷結構列表並將新輸入放入每個客戶端結構的隊列中。一個字符串是新的[編輯],因爲我不希望字符串的副本乘以所有的客戶端。但我也想避免讓多個指向字符串的指針展開並決定何時最終刪除字符串的問題。

這是一個適合共享指針的場合嗎?如果是這樣,每次我將他們推入隊列時,shared_ptr是否遞增,並在隊列中彈出時遞減?

感謝您的任何幫助。

+0

是的,雖然我認爲它不適合使用'std :: list'。 '矢量'FTW! :) – 2012-03-13 02:01:12

+0

@Billy ONeal - 爲什麼是矢量?對於不斷添加和刪除連接的內容,OP的列表選擇似乎更好。 – Duck 2012-03-13 02:07:09

+1

@Duck:'std :: list'具有較差的局部性,這通常會使性能超過一些額外的副本。 – 2012-03-13 02:09:41

回答

2

這是一個合適的使用shared_ptr。是的,使用次數將增加,因爲將推出新的shared_ptr

+0

要清楚,如果我這樣做:rawPtr = new string; shared_ptr的(原始); push(shared_ptr); ...是那個點上的refcnt 1或2?如果是2,那麼在它彈出任何彈出窗口之後它真的被刪除了,對嗎?請忽略以上的語法,我只是在尋求這個概念。 – 2012-03-13 02:45:13

+0

如果您多次推送相同的'shared_ptr',然後超出範圍,計數將是推送次數。 (一定要推送* same *'shared_ptr'的副本。) – 2012-03-13 03:04:17

4

這是一個僞垃圾收集器系統比引用計數更好的情況。

您只需要一個字符串列表,因爲您「將每個輸入都輸出到所有客戶端」。因爲您將添加到另一端並從另一端刪除,deque是合適的數據結構。

現在,每個連接只需跟蹤它發送的最後一個字符串的索引。定期地(每接收到第1000條消息,或每4MB收到一次,或類似情況),您會在所有客戶端中找到該索引的最小值,並刪除到該點爲止的字符串。這種定期檢查也是檢測遠遠落後的客戶(可能斷開連接)並恢復的機會。沒有這個檢查,一個卡住的客戶端會導致你的程序泄漏內存(即使在引用計數方案下)。

該方案比引用計數少幾倍的數據,並且還刪除了緩存爭用的一個主要點(引用計數必須從多個線程寫入,因此它們會破壞性能)。如果你不使用線程,它仍然會更快。

+0

想一想它的一個有趣的方法。它涉及如何處理慢速客戶的即將出現的問題。我將不得不考慮這一點。謝謝。 – 2012-03-13 02:49:00

+0

如果您需要偶爾將消息發送給一個客戶端,則可以將它們保留在單獨的隊列中。 – 2012-03-13 03:52:44