1

我有一个基于 websocketpp(基于 ASIO)的服务器和一个线程池。我需要分配一些资源(连接到数据库等),并确保它们将始终在同一个线程中完全使用。

所以,这是我目前拥有的:

class Server
    : public websocketpp::server<websocketpp::config::asio>
{
    Server();
    //...
    static void onMessage(Server * server,
                          websocketpp::connection_hdl hdl,
                          Server::message_ptr msg);
    //...
};

Server::Server()
{
    // ...some initialization routines.. //
    set_message_handler(
        std::bind(&onMessage,
                  this,
                  std::placeholders::_1,
                  std::placeholders::_2));
    listen(port);
    start_accept();
}

main()函数的某个地方:

    Server server;

    // estimated thread pool
    std::vector<std::thread> threads;
    threads.reserve(threadsCount);
    for(int i = 0; i < threadsCount; ++i)
    {
        threads.emplace_back(
            [&server]()
            {
                mongo::Client mongo(config); // !HERE!
                server.run();
            });
    }

如您所见mongo::Client,每个线程都有一个实例化。我的目标是将引用/指针传递给它(或将来可能添加的任何其他资源)并接收它Server::onMessage(作为附加参数)。

我完全不知道如何做到这一点。另外,我不想创建像mongo::Client * Server::acquire()/这样的分配器接口Server::release(mongo::Client *),因为它需要额外的同步。我的意图是访问(如何?)处理程序中的某种每线程“用户数据” Server::onMessage

4

2 回答 2

1

您可能想看看 WebSocket++ 的广播服务器示例。这是一个基本广播器的实现,它维护一个活动连接列表,并且由其中一个连接发送的任何消息都会发送到所有连接。

该示例使用两个线程。主线程处理服务器事件,将它们转换为添加到队列中的“动作”。工作线程(通过 创建thread t(bind(&broadcast_server::process_messages,&server_instance)))处理队列中的操作。

您可以创建多个工作线程,每个工作线程都有自己的 mongo::Client 和任何其他资源,它们从队列中获取接收到的消息并处理它们。

于 2017-05-01T13:06:18.207 回答
1

线程本地存储可能会起作用。

例如,使用 astruct来保存您的 mongo 客户端:

struct ThreadData
{
    mongo::Client client;
}

然后,声明一个线程本地ThreadData对象:

thread_local ThreadData data;

int main( int argc, char* argv[] )
{
    Server server;

    // estimated thread pool
    std::vector<std::thread> threads;
    threads.reserve(threadsCount);
    for(int i = 0; i < threadsCount; ++i)
    {
        threads.emplace_back(
            [&server]()
            {
                // 'data' is thread-local
                data.client = mongo::Client(config);
                server.run();
            });
    }
}

每个线程都作为 的线程本地副本data,因此您Server::onMessage(...)无需进一步同步即可访问它。

于 2017-04-29T17:07:25.147 回答