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