00001 // $Id: FdEvent.cc 1781 2011-04-11 12:10:19Z tho $ 00002 // 00003 // Copyright (C) 2008 00004 // Fraunhofer (FOKUS) 00005 // Competence Center NETwork research (NET), St. Augustin, GERMANY 00006 // Stefan Bund <g0dil@berlios.de> 00007 // 00008 // This program is free software; you can redistribute it and/or modify 00009 // it under the terms of the GNU General Public License as published by 00010 // the Free Software Foundation; either version 2 of the License, or 00011 // (at your option) any later version. 00012 // 00013 // This program is distributed in the hope that it will be useful, 00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 // GNU General Public License for more details. 00017 // 00018 // You should have received a copy of the GNU General Public License 00019 // along with this program; if not, write to the 00020 // Free Software Foundation, Inc., 00021 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00022 00026 #include "FdEvent.hh" 00027 #include "FdEvent.ih" 00028 00029 // Custom includes 00030 #include <sstream> 00031 00032 //#include "FdEvent.mpp" 00033 #define prefix_ 00034 //-///////////////////////////////////////////////////////////////////////////////////////////////// 00035 00036 //-///////////////////////////////////////////////////////////////////////////////////////////////// 00037 // senf::scheduler::detail::FdDispatcher 00038 00039 prefix_ senf::scheduler::detail::FdDispatcher::~FdDispatcher() 00040 { 00041 for (FdSet::iterator i (fds_.begin()); i != fds_.end(); ++i) { 00042 detail::FdManager::instance().remove(i->fd_); 00043 detail::FIFORunner::instance().dequeue(&(*i)); 00044 } 00045 } 00046 00047 prefix_ bool senf::scheduler::detail::FdDispatcher::add(FdEvent & event) 00048 { 00049 std::pair<FdSet::iterator,FdSet::iterator> range (fds_.equal_range(event)); 00050 int events (0); 00051 for (FdSet::iterator i (range.first); i != range.second; ++i) 00052 events |= i->events_; 00053 if (event.events_ & events) 00054 throw FdEvent::DuplicateEventRegistrationException() << "vinfo: " << event.v_info(); 00055 00056 if (! detail::FdManager::instance().set(event.fd_, events | event.events_, &event)) 00057 return false; 00058 00059 detail::FIFORunner::instance().enqueue(&event); 00060 fds_.insert(range.first, event); 00061 00062 return true; 00063 } 00064 00065 prefix_ void senf::scheduler::detail::FdDispatcher::remove(FdEvent & event) 00066 { 00067 fds_.erase(FdSet::current(event)); 00068 detail::FIFORunner::instance().dequeue(&event); 00069 00070 std::pair<FdSet::iterator,FdSet::iterator> range (fds_.equal_range(event)); 00071 if (range.first == range.second) 00072 detail::FdManager::instance().remove(event.fd_); 00073 else { 00074 int events (0); 00075 for (FdSet::iterator i (range.first); i != range.second; ++i) 00076 events |= i->events_; 00077 detail::FdManager::instance().set(event.fd_, events, &(*range.first)); 00078 } 00079 } 00080 00081 //-///////////////////////////////////////////////////////////////////////////////////////////////// 00082 // senf::scheduler::detail::FileDispatcher 00083 00084 prefix_ void senf::scheduler::detail::FileDispatcher::add(FdEvent & event) 00085 { 00086 std::pair<FdSet::iterator,FdSet::iterator> range (fds_.equal_range(event)); 00087 int events (0); 00088 for (FdSet::iterator i (range.first); i != range.second; ++i) 00089 events |= i->events_; 00090 if (event.events_ & events) 00091 throw FdEvent::DuplicateEventRegistrationException() << "vinfo: " << event.v_info(); 00092 00093 detail::FIFORunner::instance().enqueue(&event); 00094 fds_.insert(range.first, event); 00095 00096 detail::FdManager::instance().timeout(0); 00097 } 00098 00099 prefix_ senf::scheduler::detail::FileDispatcher::FileDispatcher() 00100 : managerTimeout_ (scheduler::detail::FdManager::instance().timeout()) 00101 {} 00102 00103 prefix_ senf::scheduler::detail::FileDispatcher::~FileDispatcher() 00104 { 00105 detail::FdManager::instance().timeout(-1); 00106 for (FdSet::iterator i (fds_.begin()); i != fds_.end(); ++i) 00107 detail::FIFORunner::instance().dequeue(&(*i)); 00108 } 00109 00110 prefix_ void senf::scheduler::detail::FileDispatcher::prepareRun() 00111 { 00112 for (FdSet::iterator i (fds_.begin()); i != fds_.end(); ++i) { 00113 i->signaledEvents_ = i->events_; 00114 i->setRunnable(); 00115 } 00116 } 00117 00118 prefix_ void senf::scheduler::detail::FileDispatcher::remove(FdEvent & event) 00119 { 00120 fds_.erase(FdSet::current(event)); 00121 detail::FIFORunner::instance().dequeue(&event); 00122 if (fds_.empty()) 00123 detail::FdManager::instance().timeout(managerTimeout_); 00124 } 00125 00126 //-///////////////////////////////////////////////////////////////////////////////////////////////// 00127 // senf::scheduler::FdEvent 00128 00129 prefix_ void senf::scheduler::FdEvent::disable() 00130 { 00131 if (enabled()) { 00132 if (pollable_) 00133 detail::FdDispatcher::instance().remove(*this); 00134 else 00135 detail::FileDispatcher::instance().remove(*this); 00136 } 00137 } 00138 00139 prefix_ void senf::scheduler::FdEvent::enable() 00140 { 00141 if (! enabled() && events_ && fd_ != -1) { 00142 if (pollable_ && detail::FdDispatcher::instance().add(*this)) 00143 return; 00144 detail::FileDispatcher::instance().add(*this); 00145 pollable_ = false; 00146 } 00147 } 00148 00149 prefix_ senf::scheduler::FdEvent & senf::scheduler::FdEvent::events(int events) 00150 { 00151 bool en = enabled(); 00152 disable(); 00153 events_ = events; 00154 if (en) 00155 enabled(); 00156 return *this; 00157 } 00158 00159 prefix_ void senf::scheduler::FdEvent::signal(int events) 00160 { 00161 detail::FdDispatcher::FdSet::iterator i (detail::FdDispatcher::FdSet::current(*this)); 00162 detail::FdDispatcher::FdSet::iterator const i_end (detail::FdDispatcher::instance().fds_.end()); 00163 bool all ((events & (EV_ERR | EV_HUP)) && ! (events & (EV_READ | EV_PRIO | EV_WRITE))); 00164 for (; i != i_end && fd_ == i->fd_; ++i) { 00165 i->signaledEvents_ = events & (EV_ERR | EV_HUP | i->events_); 00166 if (i->events_ & events || all) 00167 i->setRunnable(); 00168 } 00169 } 00170 00171 prefix_ void senf::scheduler::FdEvent::v_run() 00172 { 00173 cb_(signaledEvents_); 00174 } 00175 00176 prefix_ char const * senf::scheduler::FdEvent::v_type() 00177 const 00178 { 00179 return "fd"; 00180 } 00181 00182 prefix_ std::string senf::scheduler::FdEvent::v_info() 00183 const 00184 { 00185 std::stringstream ss; 00186 00187 ss << "fd " << fd_; 00188 if (! pollable_) 00189 ss << " (NOT pollable)"; 00190 if (events_ & EV_READ) 00191 ss << " READ"; 00192 if (events_ & EV_PRIO) 00193 ss << " PRIO"; 00194 if (events_ & EV_WRITE) 00195 ss << " WRITE"; 00196 return ss.str(); 00197 } 00198 00199 //-///////////////////////////////////////////////////////////////////////////////////////////////// 00200 #undef prefix_ 00201 //#include "FdEvent.mpp" 00202 00203 00204 // Local Variables: 00205 // mode: c++ 00206 // fill-column: 100 00207 // comment-column: 40 00208 // c-file-style: "senf" 00209 // indent-tabs-mode: nil 00210 // ispell-local-dictionary: "american" 00211 // compile-command: "scons -u test" 00212 // End: