繁体   English   中英

如何将每线程用户数据传递给asio处理程序?

[英]How to pass per-thread user data into asio handler?

我有一个基于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 我的目标是将ref / pointer传递给它(或将来可能添加的任何其他资源)并在Server::onMessage接收它(作为附加参数)。

我完全不知道如何执行此操作。 另外,我不想创建像mongo::Client * Server::acquire() / Server::release(mongo::Client *)这样的分配器接口,因为它需要额外的同步。 我的意图是在Server::onMessage处理程序中访问(如何?)某种类型的每线程“ userdata”。

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

使用例如一个struct来保存您的mongo Client:

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(...)没有进一步的同步。

您可能想看一下WebSocket ++的broadcast_server示例 这是基本广播器的实现,该广播器维护活动连接的列表,并且由连接之一发送的任何消息都将发送到所有连接。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM