SelectorImplBSD.cpp

Go to the documentation of this file.
00001 /****************** <VPR heading BEGIN do not edit this line> *****************
00002  *
00003  * VR Juggler Portable Runtime
00004  *
00005  * Original Authors:
00006  *   Allen Bierbaum, Patrick Hartling, Kevin Meinert, Carolina Cruz-Neira
00007  *
00008  * -----------------------------------------------------------------
00009  * File:          $RCSfile$
00010  * Date modified: $Date: 2005-01-01 11:48:13 -0600 (Sat, 01 Jan 2005) $
00011  * Version:       $Revision: 16520 $
00012  * -----------------------------------------------------------------
00013  *
00014  ****************** <VPR heading END do not edit this line> ******************/
00015 
00016 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
00017  *
00018  * VR Juggler is (C) Copyright 1998-2005 by Iowa State University
00019  *
00020  * Original Authors:
00021  *   Allen Bierbaum, Christopher Just,
00022  *   Patrick Hartling, Kevin Meinert,
00023  *   Carolina Cruz-Neira, Albert Baker
00024  *
00025  * This library is free software; you can redistribute it and/or
00026  * modify it under the terms of the GNU Library General Public
00027  * License as published by the Free Software Foundation; either
00028  * version 2 of the License, or (at your option) any later version.
00029  *
00030  * This library is distributed in the hope that it will be useful,
00031  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00032  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00033  * Library General Public License for more details.
00034  *
00035  * You should have received a copy of the GNU Library General Public
00036  * License along with this library; if not, write to the
00037  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00038  * Boston, MA 02111-1307, USA.
00039  *
00040  *************** <auto-copyright.pl END do not edit this line> ***************/
00041 
00042 #include <vpr/vprConfig.h>
00043 
00044 #include <stdio.h>
00045 #include <string.h>
00046 #include <unistd.h>
00047 #include <sys/types.h>
00048 
00049 #ifdef HAVE_BSTRING_H
00050 #  include <bstring.h>
00051 #endif
00052 
00053 #include <sys/time.h>
00054 #include <errno.h>
00055 
00056 #include <vpr/md/POSIX/IO/SelectorImplBSD.h>
00057 #include <vpr/Util/Assert.h>
00058 
00059 
00060 namespace vpr
00061 {
00062 
00066 bool SelectorImplBSD::addHandle (vpr::IOSys::Handle handle, vpr::Uint16 mask)
00067 {
00068    bool status;
00069 
00070    if ( getHandle(handle) == mPollDescs.end() )
00071    {
00072       BSDPollDesc new_desc;
00073       new_desc.fd        = handle;
00074       new_desc.in_flags  = mask;
00075       new_desc.out_flags = 0;
00076 
00077       mPollDescs.push_back(new_desc);
00078       status = true;
00079    }
00080    else
00081    {
00082       status = false;
00083    }
00084 
00085    return status;
00086 }
00087 
00091 bool SelectorImplBSD::removeHandle (vpr::IOSys::Handle handle)
00092 {
00093    bool status;
00094    std::vector<BSDPollDesc>::iterator i = getHandle(handle);
00095 
00096    if ( mPollDescs.end() == i )
00097    {
00098       status = false;
00099    }
00100    else
00101    {
00102       mPollDescs.erase(i);
00103       status = true;
00104    }
00105 
00106    return status;
00107 }
00108 
00110 bool SelectorImplBSD::setIn (vpr::IOSys::Handle handle, vpr::Uint16 mask)
00111 {
00112    bool status;
00113    std::vector<BSDPollDesc>::iterator i = getHandle(handle);
00114 
00115    if ( mPollDescs.end() == i )
00116    {
00117       status = false;
00118    }
00119    else
00120    {
00121       (*i).in_flags = mask;
00122       status = true;
00123    }
00124 
00125    return status;
00126 }
00127 
00129 vpr::Uint16 SelectorImplBSD::getIn (vpr::IOSys::Handle handle)
00130 {
00131    vpr::Uint16 flags;
00132    std::vector<BSDPollDesc>::iterator i = getHandle(handle);
00133 
00134    if ( mPollDescs.end() == i )
00135    {
00136       // XXX: This is VERY bad thing to do.  Need to have an error code instead
00137       flags = 0;
00138    }
00139    else
00140    {
00141       flags = (*i).in_flags;
00142    }
00143 
00144    return flags;
00145 }
00146 
00148 vpr::Uint16 SelectorImplBSD::getOut (vpr::IOSys::Handle handle)
00149 {
00150    vpr::Uint16 flags;
00151    std::vector<BSDPollDesc>::iterator i = getHandle(handle);
00152 
00153    if ( mPollDescs.end() == i )
00154    {
00155       // XXX: This is VERY bad thing to do.  Need to have an error code instead
00156       flags = 0;
00157    }
00158    else
00159    {
00160       flags = (*i).out_flags;
00161    }
00162 
00163    return flags;
00164 }
00165 
00169 vpr::ReturnStatus SelectorImplBSD::select (vpr::Uint16& numWithEvents,
00170                                            const vpr::Interval timeout)
00171 {
00172    vpr::ReturnStatus ret_val;
00173    int result, last_fd;
00174    fd_set read_set, write_set, exception_set;
00175    std::vector<BSDPollDesc>::iterator i;
00176    struct timeval timeout_obj;
00177 
00178    // Zero everything out before doing anything else.
00179    FD_ZERO(&read_set);
00180    FD_ZERO(&write_set);
00181    FD_ZERO(&exception_set);
00182 
00183    last_fd = -1;
00184 
00185    for ( i = mPollDescs.begin(); i != mPollDescs.end(); ++i )
00186    {
00187       (*i).out_flags = 0;
00188 
00189       if ( (*i).in_flags & SelectorBase::Read )
00190       {
00191          FD_SET((*i).fd, &read_set);
00192       }
00193 
00194       if ( (*i).in_flags & SelectorBase::Write )
00195       {
00196          FD_SET((*i).fd, &write_set);
00197       }
00198 
00199       if ( (*i).in_flags & SelectorBase::Except )
00200       {
00201          FD_SET((*i).fd, &exception_set);
00202       }
00203 
00204       // Find the highest-valued file descriptor.
00205       if ( last_fd < (*i).fd )
00206       {
00207          last_fd = (*i).fd;
00208       }
00209    }
00210 
00211    if ( timeout == vpr::Interval::NoWait )
00212    {
00213       timeout_obj.tv_sec  = 0;
00214       timeout_obj.tv_usec = 0;
00215    }
00216    else
00217    {
00218       // Apparently select(2) doesn't like if the microsecond member has a
00219       // time larger than 1 second, so if timeout (given in milliseconds) is
00220       // larger than 1000, we have to split it up between the seconds and
00221       // microseconds members.
00222       if ( timeout.msec() >= 1000 )
00223       {
00224          timeout_obj.tv_sec  = timeout.msec() / 1000;
00225          timeout_obj.tv_usec = (timeout.msec() % 1000) * 1000000;
00226       }
00227       else
00228       {
00229          timeout_obj.tv_sec  = 0;
00230          timeout_obj.tv_usec = timeout.msec() * 1000;
00231       }
00232    }
00233 
00234    // If timeout is 0, this will be the same as polling the descriptors.  To
00235    // get no timeout, NULL must be passed to select(2).
00236    result = ::select(last_fd + 1, &read_set, &write_set, &exception_set,
00237                      (timeout != vpr::Interval::NoTimeout) ? &timeout_obj : NULL);
00238 
00239    // D'oh!
00240    if ( -1 == result )
00241    {
00242       fprintf(stderr, "SelectorImplBSD::select: Error selecting: %s\n",
00243               strerror(errno));
00244       numWithEvents = 0;
00245       ret_val.setCode(ReturnStatus::Fail);
00246    }
00247    // Timeout.
00248    else if ( 0 == result )
00249    {
00250       numWithEvents = 0;
00251       ret_val.setCode(ReturnStatus::Timeout);
00252    }
00253    // We got one!
00254    else
00255    {
00256       for ( i = mPollDescs.begin(); i != mPollDescs.end(); ++i )
00257       {
00258          if ( FD_ISSET((*i).fd, &read_set) )
00259          {
00260             (*i).out_flags |= SelectorBase::Read;
00261          }
00262 
00263          if ( FD_ISSET((*i).fd, &write_set) )
00264          {
00265             (*i).out_flags |= SelectorBase::Write;
00266          }
00267 
00268          if ( FD_ISSET((*i).fd, &exception_set) )
00269          {
00270             (*i).out_flags |= SelectorBase::Except;
00271          }
00272       }
00273 
00274       numWithEvents = result;
00275    }
00276 
00277    return ret_val;
00278 }
00279 
00283 std::vector<SelectorImplBSD::BSDPollDesc>::iterator SelectorImplBSD::getHandle (int handle)
00284 {
00285    // XXX: Should probably be replaced by a map in the future for speed
00286 
00287    for ( std::vector<BSDPollDesc>::iterator i=mPollDescs.begin();
00288        i != mPollDescs.end();++i )
00289    {
00290       if ( (*i).fd == handle )
00291          return i;
00292    }
00293 
00294    return mPollDescs.end();
00295 }
00296 
00297 }  // namespace vpr

Generated on Thu Jan 4 10:52:10 2007 for VR Juggler Portable Runtime by  doxygen 1.5.1