src/Network/Reactor.cc
author Tero Marttila <terom@fixme.fi>
Fri, 16 Jan 2009 22:03:49 +0200
changeset 400 d64bf28c4340
parent 384 6d387796b139
permissions -rw-r--r--
more documentation tweaking, all Network/ files now have a @file comment. Fix Platform.h -> Platform.hh, and Buffer.hh + Packet.cc
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
NetworkReactor::NetworkReactor (void) :
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
     5
    sockets()
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
     6
{
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
void NetworkReactor::poll (timeval *timeout) {
384
6d387796b139 fix select EINTR issues
terom
parents: 380
diff changeset
    11
    int ret;
6d387796b139 fix select EINTR issues
terom
parents: 380
diff changeset
    12
400
d64bf28c4340 more documentation tweaking, all Network/ files now have a @file comment. Fix Platform.h -> Platform.hh, and Buffer.hh + Packet.cc
Tero Marttila <terom@fixme.fi>
parents: 384
diff changeset
    13
    // start counting the maximum fd from 0, select will be given nfds=1 if empty
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    14
    int fd_max = 0;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    15
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    16
    // zero our fdsets
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    17
    fd_set read, write;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    18
    FD_ZERO(&read);
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    19
    FD_ZERO(&write);
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    20
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    21
    // inspect our sockets
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    22
    for (std::list<NetworkSocket*>::iterator it = sockets.begin(); it != sockets.end(); it++) {
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    23
        NetworkSocket *socket = *it;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    24
    
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    25
        // ask socket what events it wants
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    26
        NetworkPollMask mask = socket->get_poll();
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    27
400
d64bf28c4340 more documentation tweaking, all Network/ files now have a @file comment. Fix Platform.h -> Platform.hh, and Buffer.hh + Packet.cc
Tero Marttila <terom@fixme.fi>
parents: 384
diff changeset
    28
        // ignore if nothing
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    29
        if (mask) {
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    30
            // socket file descriptor...
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    31
            int fd = socket->get_socket();
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    32
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    33
            // ignore invalid FDs
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    34
            if (fd < 0)
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    35
                continue;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    36
            
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    37
            // update fd_max?
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    38
            if (fd > fd_max)
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    39
                fd_max = fd;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    40
            
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    41
            // read...
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    42
            if (mask & POLL_READ)
400
d64bf28c4340 more documentation tweaking, all Network/ files now have a @file comment. Fix Platform.h -> Platform.hh, and Buffer.hh + Packet.cc
Tero Marttila <terom@fixme.fi>
parents: 384
diff changeset
    43
                FD_SET(fd, &read);
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    44
            
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    45
            // write...
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    46
            if (mask & POLL_WRITE)
400
d64bf28c4340 more documentation tweaking, all Network/ files now have a @file comment. Fix Platform.h -> Platform.hh, and Buffer.hh + Packet.cc
Tero Marttila <terom@fixme.fi>
parents: 384
diff changeset
    47
                FD_SET(fd, &write);
380
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
384
6d387796b139 fix select EINTR issues
terom
parents: 380
diff changeset
    51
    // loop select() on EINTR
6d387796b139 fix select EINTR issues
terom
parents: 380
diff changeset
    52
    do {
6d387796b139 fix select EINTR issues
terom
parents: 380
diff changeset
    53
        // we never care about except, and pass NULL fdsets if they are empty
6d387796b139 fix select EINTR issues
terom
parents: 380
diff changeset
    54
        ret = select(
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    55
            fd_max + 1, 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    56
            fd_max ? &read : NULL, 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    57
            fd_max ? &write : NULL, 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    58
            NULL, 
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    59
            timeout
384
6d387796b139 fix select EINTR issues
terom
parents: 380
diff changeset
    60
        );
6d387796b139 fix select EINTR issues
terom
parents: 380
diff changeset
    61
    } while (ret < 0 && errno == EINTR);
6d387796b139 fix select EINTR issues
terom
parents: 380
diff changeset
    62
    
6d387796b139 fix select EINTR issues
terom
parents: 380
diff changeset
    63
    // error?
6d387796b139 fix select EINTR issues
terom
parents: 380
diff changeset
    64
    if (ret < 0)
380
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    65
        throw NetworkReactorError("select");
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    66
    
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    67
    // ignore if we just timed out
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    68
    if (ret == 0)
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    69
        return;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    70
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    71
    // notify up to <ret> socket-events
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    72
    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
    73
        NetworkSocket *socket = *it;
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
        // socket file descriptor...
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    76
        int fd = socket->get_socket();
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    77
            
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    78
        // ignore invalid FDs
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    79
        if (fd < 0)
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    80
            continue;
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
        // mask of events detected
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    83
        NetworkPollMask mask = 0;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    84
        
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    85
        // detect read
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    86
        if (FD_ISSET(fd, &read)) {
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    87
            mask |= POLL_READ;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    88
            ret--;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    89
        }
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    90
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    91
        // detect write
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    92
        if (FD_ISSET(fd, &write)) {
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    93
            mask |= POLL_WRITE;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    94
            ret--;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    95
        }
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    96
        
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    97
        // notify?
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    98
        if (mask)
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
    99
            socket->notify(mask);
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
   100
    }
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
   101
}
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
   102
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
   103
// the global reactor
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
   104
static NetworkReactor g_reactor;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
   105
NetworkReactor *NetworkReactor::current = &g_reactor;
d193dd1d8a7e new NetworkReactor, fix everything to actually work
terom
parents:
diff changeset
   106