1 // ANNA - Anna is Not Nothingness Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // http://redmine.teslayout.com/projects/anna-suite
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
17 // * Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
37 #include <anna/comm/internal/Poll.hpp>
39 //-----------------------------------------------------------------------------------
40 // RECORDAR QUE ESTA CLASE SOLO SE USA EN LA VERSION SINGLE-THREAD DEL
42 //-----------------------------------------------------------------------------------
46 void comm::Poll::setTimeout(const Millisecond &timeout)
48 if((a_timeout.tv_sec = timeout / 1000) == 0)
49 a_timeout.tv_usec = timeout * 1000;
51 a_timeout.tv_usec = 0;
53 a_ptrTimeout = (a_timeout.tv_sec != 0 || a_timeout.tv_usec != 0) ? &a_timeout : NULL;
56 //--------------------------------------------------------------------------------------------
57 // Si a_ptrTimeout != NULL => se devuelve el tiempo que ha sobrado de la espera maxima
58 // establecida (en Solaris este puntero no se modifica para nada)
60 // Para las dos implementacion el NULL => espera hasta que llegue un mensaje.
61 //--------------------------------------------------------------------------------------------
62 void comm::Poll::waitMessage()
63 throw(RuntimeException) {
64 if(a_ptrTimeout == NULL)
65 a_pollr = select(a_maxfd, (fd_set*) anna_memcpy(&a_fdset, &a_fdmask, sizeof(fd_set)), NULL);
68 timeval timeout(a_timeout);
69 a_pollr = select(a_maxfd, (fd_set*) anna_memcpy(&a_fdset, &a_fdmask, sizeof(fd_set)), &timeout);
71 a_pollr = select(a_maxfd, (fd_set*) anna_memcpy(&a_fdset, &a_fdmask, sizeof(fd_set)), a_ptrTimeout);
76 //-----------------------------------------------------------------------------------------
77 // Se ha detectado una condicion de error. Se recibe trafico por fd = { 16, 19} y el
78 // tramiento de 16 => cierre de 19 mediante comm::Communicator::attach => el a_ifd no
79 // llegaba nunca a tratar al 19, porque el a_maxfd ha sido modificado con 16, pero el a_pollr
80 // sigue indicado que queda un fd por tratar. ver Poll::erase
82 // (1) Una vez que ha tratado detectado la activada desactiva el indicador
83 //-----------------------------------------------------------------------------------------
84 int comm::Poll::fetch()
89 if(FD_ISSET(a_ifd, &a_fdset)) {
90 FD_CLR(a_ifd, &a_fdset); // (1)
100 if(++ a_ifd > a_maxfd)
107 void comm::Poll::insert(const int fd)
109 FD_SET(fd, &a_fdmask);
111 if(a_maxfd < fd) a_maxfd = fd;
114 a_ifd = a_minfd = fd;
117 //---------------------------------------------------------------------------------------
118 // Hay que comprobar que el 'fd' que vamos a eliminar de la lista no este en la lista
119 // de pendientes de tratar.
120 //---------------------------------------------------------------------------------------
121 void comm::Poll::erase(const int fd)
123 FD_CLR(fd, &a_fdmask);
125 if(FD_ISSET(fd, &a_fdset) && a_pollr > 0) { // (1)
126 FD_CLR(fd, &a_fdset);
130 if(fd == a_maxfd || fd == a_minfd) {
131 const int max = a_maxfd;
135 for(int ifd = 0; ifd <= max; ifd ++) {
136 if(FD_ISSET(ifd, &a_fdmask)) {
137 if(a_maxfd < ifd) a_maxfd = ifd;
139 if(ifd < a_minfd) a_minfd = ifd;