複数のリクエストを 1 つのスレッドに多重化する標準的な方法は、Reactor パターンを使用することです。中央のオブジェクト (通常は SelectServer、SocketServer、または IOService と呼ばれます) は、実行中のリクエストからすべてのソケットを監視し、ソケットが読み取りまたは書き込みを続行する準備が整ったときにコールバックを発行します。
他の人が述べているように、自分でロールバックすることはおそらく悪い考えです。タイムアウト、エラー、およびクロス プラットフォーム互換性 (Linux の epoll、bsd の kqueue、Windows の iocp など) の処理は注意が必要です。本番システムにはboost::asioまたはlibeventを使用してください。
これは、アイデアを提供するためのスケルトン SelectServer (コンパイルされますが、テストされていません) です。
#include <sys/select.h>
#include <functional>
#include <map>
class SelectServer {
public:
enum ReadyType {
READABLE = 0,
WRITABLE = 1
};
void CallWhenReady(ReadyType type, int fd, std::function<void()> closure) {
SocketHolder holder;
holder.fd = fd;
holder.type = type;
holder.closure = closure;
socket_map_[fd] = holder;
}
void Run() {
fd_set read_fds;
fd_set write_fds;
while (1) {
if (socket_map_.empty()) break;
int max_fd = -1;
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
for (const auto& pr : socket_map_) {
if (pr.second.type == READABLE) {
FD_SET(pr.second.fd, &read_fds);
} else {
FD_SET(pr.second.fd, &write_fds);
}
if (pr.second.fd > max_fd) max_fd = pr.second.fd;
}
int ret_val = select(max_fd + 1, &read_fds, &write_fds, 0, 0);
if (ret_val <= 0) {
// TODO: Handle error.
break;
} else {
for (auto it = socket_map_.begin(); it != socket_map_.end(); ) {
if (FD_ISSET(it->first, &read_fds) ||
FD_ISSET(it->first, &write_fds)) {
it->second.closure();
socket_map_.erase(it++);
} else {
++it;
}
}
}
}
}
private:
struct SocketHolder {
int fd;
ReadyType type;
std::function<void()> closure;
};
std::map<int, SocketHolder> socket_map_;
};