2012-03-13 69 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