C ++对象和线程

时间:2014-09-05 12:17:43

标签: c++ multithreading object vector

我正在做一个简单的服务器应用,你可以有多个连接,每个连接都是一个线程。这是我想要的样子(它不起作用),有一个线程集合,每个线程实例化类连接的对象:

class connection{};

class server{
std::vector<std::thread> active_connections;
public:
    void listen() {active_connections.push_back(std::thread(connection));}
};

我一直在寻找解决方案,但我能找到的最好的是一些成员函数线程。当我测试它时,解决方案变得非常错误,例如:

class connection{};

class server{
std::vector<std::thread> active_connections;
public:
    void new_connection() { ... }
    void listen() { 
        active_connections.push_back(std::thread(&server::new_connection,this)); }
    };

消息是:错误:使用已删除的函数'std :: thread :: thread(const std :: thread&amp;)。 这是否意味着std :: thread类想要复制服务器类?我不太了解C ++,所以请不要火焰,我只是问。

谢谢!

编辑:

这就是发生这种情况的地方:

void server::do_listen()
{   
    int addr_size = sizeof(sockaddr_in);
    sockaddr_in client_sock;
    connection_info cn_info;

    while(true)
    {
        int csock;
        if((csock = accept(server_sock, (sockaddr*)&client_sock, (socklen_t*)&addr_size)) != -1)
        {
            printf("Incomming connection from %s.\n", inet_ntoa(client_sock.sin_addr));
            memset(&cn_info,0, sizeof(connection_info));
            cn_info.sock_addr = client_sock;
            cn_info.sock = csock;
            std::thread thr(&server::new_connection, *this, cn_info);
            thr.join();
        }

    }
}

到目前为止。 server::new_connection()仍为空。

3 个答案:

答案 0 :(得分:3)

问题在于:

std::thread thr(&server::new_connection, *this, cn_info);
                                         ^

您正在绑定服务器对象的副本;这是不可复制的,因为它包含(一个容器)不可复制的thread个对象。相反,绑定一个指针:

std::thread thr(&server::new_connection, this, cn_info);

有些人可能会发现lambda更具可读性;这会按值捕获this指针和cn_info

std::thread thr([=]{new_connection(cn_info);});

正如评论员所提到的,你可以通过绑定reference wrapper来混淆解决方案:

std::thread thr(&server::new_connection, std::ref(*this), cn_info);

但我更愿意在可能的情况下删除而不是添加复杂性。

答案 1 :(得分:2)

  

这是否意味着std :: thread类想要复制服务器类?

不,这意味着std::thread的副本会在某个地方制作,但NonCopyable中的std::thread被禁止(请注意列表中的thread(const thread&) = delete;建设者)。

您应该删除执行thread副本的任何代码。您发布的那个没有执行此类复制。

在场景后面制作副本的示例&#34;将是线程变量向量中的push_back,即:

std::thread myThread;
myVector.push_back(myThread);

在您的代码中:

active_connections.push_back(std::thread(&server::new_connection,this)); 

当你正在推回一个临时的时候,它不会被复制但会被移入矢量。

答案 2 :(得分:0)

更多设计问题给你作者:

您为一个连接创建一个线程。如果你有十个连接,你有十个线程。但是如果你想要处理10000个连接,你会怎么做?我不确定您的操作系统是否喜欢它。

一种更好的连接处理方法 - 仅在我看来 - 如果你只有N个线程来处理你的网络连接。如果你的电脑有例如六个核心,你可以只为网络的东西花一个,两个或更多的线程。所以你有一个特定大小的线程池。

proactor模式对你来说很有意思:

http://en.wikipedia.org/wiki/Proactor_pattern

如果您正在寻找可以处理此类事情的库,您可以查看即将推出的名为Boost.Asynchronous的C ++ Boost库:

https://github.com/henry-ch/asynchronous

这个库仍在开发中,但非常好。我用库制作了一些简单的客户端/服务器应用程序。