在poll上添加/删除描述符的优雅方法

Sha*_*dor 5 c c++ unix polling

我必须在一个处理大约1000个描述符poll(我不能使用epoll它特定于Linux),我必须能够动态添加/删除它们(处理新连接并删除关闭).

这意味着我应该在每次迭代时重新组合描述符数组.

从技术角度来看,这是显而易见的,但有人知道这样做的一种美妙方式吗?

Mos*_*ieb 5

我会将死的描述符保留在数组中,并偶尔清除一次。我还会维护每个描述符的位置,以便于删除,但这可以进一步优化。诀窍是将无效的描述符保留在数组中,而不是每次都重新排列数组。

例如:

struct pollfd pfds[MY_MAX_FDS];
int nfds = 0;
enum { INVALID_FD = -1 };
....

typedef std::map<int,int> desc_to_index_t;
desc_to_index_t d2i;
....
// add descriptor
if (nfds == MY_MAX_FDS){
    // purge old fds
    // go through pfds and remove everything that has invalid fd
    // pfds should point to a condensed array of valid objects and nfds should be updated as well, as long as d2i.
}
pfds[nfds] = { desc, events, revents};
d2i.insert(std::make_pair(desc,nfds));
++nfds;
....
// remove descriptor
desc_to_index_t::iterator it = d2i.find(desc);
assert(it != d2i.end());
pfds[it->second] = { INVALID_FD, 0, 0 };
d2i.erase(it);
Run Code Online (Sandbox Code Playgroud)

这样,您只需在超过某个阈值时清除,而无需每次都构建阵列。

  • +1 这可能是你真正能做到的最好的了,_除了使用 epoll_。当然,你仍然可以一个一个地删除描述符,因为它们只是你程序地址空间中的一个数组,而且每次都会重新上传,但是……请注意,虽然 epoll 是 Linux 特定的,但 kqueue存在于 epoll 不存在的地方。使用一个小的抽象层(不同的系统调用,略有不同的语义)应该可以同时使用两者。等等,有人说“libevent”吗? (2认同)