如何使用epoll管理Connection的生命周期(void * event.data.ptr)

时间:2018-03-20 02:11:09

标签: c++ c++11 smart-pointers epoll

我正在使用C ++实现epoll。 我想学习nginx以使用(void*) event.data.ptrConnection相关联。 Connection是一个智能指针。但是在void*之间我需要将智能指针转换为原始指针。

转换和获取过程中引用的数量没有增加,显然程序会崩溃。 所以我不使用智能指针。

我使用newdelete。但它太可怕了 如何管理Connection的生命周期?

int nfds = epoll_wait(epollfd, event_list, 100, -1);
for (int n = 0; n < nfds; ++n) {
  auto event = event_list[n];
  auto revents = event.events;

  if (revents & EPOLLIN) {
    if (event.data.fd  == listen_fd_) {
      int fd = handleAccept(listen_fd_);
      auto conn_ptr = std::make_shared<Connection>(fd, connections_manager_);
      //connecions_manager_ is std::set<std::shared_ptr<Connection>>
      //it use start, stop and stop_all manage Connection.
      connections_manager_.start(conn_ptr);
      struct epoll_event ev;
      ev.events = EPOLLIN | EPOLLET;
      ev.data.ptr = static_cast<void*>(conn_ptr.get());
      if (epoll_ctl(event_.getEpollFd(), EPOLL_CTL_ADD, fd, &ev) == -1) {
        std::cout << "epoll_ctl failed. fd is " << fd << '\n';
        perror("epoll_ctl: fd_");
        exit(EXIT_FAILURE);
      }
      continue;
    }
    auto conn = static_cast<Connection *>(event.data.ptr);
    conn->start();
  }
}

1 个答案:

答案 0 :(得分:0)

以下是您可能希望实施的一般概念:

  • 保留您创建的所有Connection个对象的列表。可以使用简单的C风格数组,但您可以检查使用std::vectorstd::mapstd::unordered_map进行Connection对象簿记的可能性。
  • 每当您创建新的Connection时,都会将其添加到列表中,然后再将其添加到epoll池中。我建议使用单独的方法add()
  • 同样,在关闭Connection(来自主机或客户端)时,您需要从epoll池中删除它。但是,它会出现在您的连接列表中。你可能需要一个标志,例如isClosed并为true设置已关闭的连接。不要删除Connection主事件循环中的epoll个对象。此外,您还需要一些东西来确定是否有一些数据需要在关闭您身边的连接之前发送。客户端可能正在等待从服务器接收数据。
  • 对于这些已关闭连接的垃圾回收,您可以使用具有固定时间间隔的单独线程来浏览列表并删除已关闭的连接。

通常,您可能需要一些waitlistenaddremove等的包装方法来分解您的操作。它更容易管理。此外,您可能有专门用于读/写操作的单独线程池。接受主事件循环中的连接就好了。

希望有所帮助! 如果您想进一步讨论,请告诉我。