|
1 |
|
2 #include "Reactor.hh" |
|
3 |
|
4 |
|
5 NetworkReactor::NetworkReactor (void) : |
|
6 sockets() |
|
7 { |
|
8 |
|
9 } |
|
10 |
|
11 void NetworkReactor::poll (timeval *timeout) { |
|
12 // start counting the maximum fd from -1, so that select is given nfds=0 if our list is empty |
|
13 int fd_max = 0; |
|
14 |
|
15 // zero our fdsets |
|
16 fd_set read, write; |
|
17 FD_ZERO(&read); |
|
18 FD_ZERO(&write); |
|
19 |
|
20 // inspect our sockets |
|
21 for (std::list<NetworkSocket*>::iterator it = sockets.begin(); it != sockets.end(); it++) { |
|
22 NetworkSocket *socket = *it; |
|
23 |
|
24 // ask socket what events it wants |
|
25 NetworkPollMask mask = socket->get_poll(); |
|
26 |
|
27 // set read/write |
|
28 if (mask) { |
|
29 // socket file descriptor... |
|
30 int fd = socket->get_socket(); |
|
31 |
|
32 // ignore invalid FDs |
|
33 if (fd < 0) |
|
34 continue; |
|
35 |
|
36 // update fd_max? |
|
37 if (fd > fd_max) |
|
38 fd_max = fd; |
|
39 |
|
40 // read... |
|
41 if (mask & POLL_READ) |
|
42 FD_SET(socket->get_socket(), &read); |
|
43 |
|
44 // write... |
|
45 if (mask & POLL_WRITE) |
|
46 FD_SET(socket->get_socket(), &write); |
|
47 } |
|
48 } |
|
49 |
|
50 // run select |
|
51 int ret; |
|
52 |
|
53 // we never care about except |
|
54 // pass NULL fdsets if they are empty |
|
55 if ((ret = select( |
|
56 fd_max + 1, |
|
57 fd_max ? &read : NULL, |
|
58 fd_max ? &write : NULL, |
|
59 NULL, |
|
60 timeout |
|
61 )) < 0) |
|
62 throw NetworkReactorError("select"); |
|
63 |
|
64 // ignore if we just timed out |
|
65 if (ret == 0) |
|
66 return; |
|
67 |
|
68 // notify up to <ret> socket-events |
|
69 for (std::list<NetworkSocket*>::iterator it = sockets.begin(); it != sockets.end() && ret > 0; it++) { |
|
70 NetworkSocket *socket = *it; |
|
71 |
|
72 // socket file descriptor... |
|
73 int fd = socket->get_socket(); |
|
74 |
|
75 // ignore invalid FDs |
|
76 if (fd < 0) |
|
77 continue; |
|
78 |
|
79 // mask of events detected |
|
80 NetworkPollMask mask = 0; |
|
81 |
|
82 // detect read |
|
83 if (FD_ISSET(fd, &read)) { |
|
84 mask |= POLL_READ; |
|
85 ret--; |
|
86 } |
|
87 |
|
88 // detect write |
|
89 if (FD_ISSET(fd, &write)) { |
|
90 mask |= POLL_WRITE; |
|
91 ret--; |
|
92 } |
|
93 |
|
94 // notify? |
|
95 if (mask) |
|
96 socket->notify(mask); |
|
97 } |
|
98 } |
|
99 |
|
100 // the global reactor |
|
101 static NetworkReactor g_reactor; |
|
102 NetworkReactor *NetworkReactor::current = &g_reactor; |
|
103 |