eventloop.cpp
Go to the documentation of this file.
00001 /* 00002 * 00003 * D-Bus++ - C++ bindings for D-Bus 00004 * 00005 * Copyright (C) 2005-2007 Paolo Durante <shackan@gmail.com> 00006 * 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library 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 GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00021 * 00022 */ 00023 00024 #ifdef HAVE_CONFIG_H 00025 #include <config.h> 00026 #endif 00027 00028 #include <dbus-c++/eventloop.h> 00029 #include <dbus-c++/debug.h> 00030 00031 #include <sys/poll.h> 00032 #include <sys/time.h> 00033 00034 #include <dbus/dbus.h> 00035 00036 using namespace DBus; 00037 using namespace std; 00038 00039 static double millis(timeval tv) 00040 { 00041 return (tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0); 00042 } 00043 00044 DefaultTimeout::DefaultTimeout(int interval, bool repeat, DefaultMainLoop *ed) 00045 : _enabled(true), _interval(interval), _repeat(repeat), _expiration(0), _data(0), _disp(ed) 00046 { 00047 timeval now; 00048 gettimeofday(&now, NULL); 00049 00050 _expiration = millis(now) + interval; 00051 00052 _disp->_mutex_t.lock(); 00053 _disp->_timeouts.push_back(this); 00054 _disp->_mutex_t.unlock(); 00055 } 00056 00057 DefaultTimeout::~DefaultTimeout() 00058 { 00059 _disp->_mutex_t.lock(); 00060 _disp->_timeouts.remove(this); 00061 _disp->_mutex_t.unlock(); 00062 } 00063 00064 DefaultWatch::DefaultWatch(int fd, int flags, DefaultMainLoop *ed) 00065 : _enabled(true), _fd(fd), _flags(flags), _state(0), _data(0), _disp(ed) 00066 { 00067 _disp->_mutex_w.lock(); 00068 _disp->_watches.push_back(this); 00069 _disp->_mutex_w.unlock(); 00070 } 00071 00072 DefaultWatch::~DefaultWatch() 00073 { 00074 _disp->_mutex_w.lock(); 00075 _disp->_watches.remove(this); 00076 _disp->_mutex_w.unlock(); 00077 } 00078 00079 DefaultMutex::DefaultMutex() 00080 { 00081 pthread_mutex_init(&_mutex, NULL); 00082 } 00083 00084 DefaultMutex::DefaultMutex(bool recursive) 00085 { 00086 if (recursive) 00087 { 00088 pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; 00089 _mutex = recmutex; 00090 } 00091 else 00092 { 00093 pthread_mutex_init(&_mutex, NULL); 00094 } 00095 } 00096 00097 DefaultMutex::~DefaultMutex() 00098 { 00099 pthread_mutex_destroy(&_mutex); 00100 } 00101 00102 void DefaultMutex::lock() 00103 { 00104 pthread_mutex_lock(&_mutex); 00105 } 00106 00107 void DefaultMutex::unlock() 00108 { 00109 pthread_mutex_unlock(&_mutex); 00110 } 00111 00112 DefaultMainLoop::DefaultMainLoop() : 00113 _mutex_w(true) 00114 { 00115 } 00116 00117 DefaultMainLoop::~DefaultMainLoop() 00118 { 00119 _mutex_w.lock(); 00120 00121 DefaultWatches::iterator wi = _watches.begin(); 00122 while (wi != _watches.end()) 00123 { 00124 DefaultWatches::iterator wmp = wi; 00125 ++wmp; 00126 _mutex_w.unlock(); 00127 delete(*wi); 00128 _mutex_w.lock(); 00129 wi = wmp; 00130 } 00131 _mutex_w.unlock(); 00132 00133 _mutex_t.lock(); 00134 00135 DefaultTimeouts::iterator ti = _timeouts.begin(); 00136 while (ti != _timeouts.end()) 00137 { 00138 DefaultTimeouts::iterator tmp = ti; 00139 ++tmp; 00140 _mutex_t.unlock(); 00141 delete(*ti); 00142 _mutex_t.lock(); 00143 ti = tmp; 00144 } 00145 _mutex_t.unlock(); 00146 } 00147 00148 void DefaultMainLoop::dispatch() 00149 { 00150 _mutex_w.lock(); 00151 00152 int nfd = _watches.size(); 00153 00154 if (_fdunlock) 00155 { 00156 nfd = nfd + 2; 00157 } 00158 00159 pollfd fds[nfd]; 00160 00161 DefaultWatches::iterator wi = _watches.begin(); 00162 00163 for (nfd = 0; wi != _watches.end(); ++wi) 00164 { 00165 if ((*wi)->enabled()) 00166 { 00167 fds[nfd].fd = (*wi)->descriptor(); 00168 fds[nfd].events = (*wi)->flags(); 00169 fds[nfd].revents = 0; 00170 00171 ++nfd; 00172 } 00173 } 00174 00175 if (_fdunlock) 00176 { 00177 fds[nfd].fd = _fdunlock[0]; 00178 fds[nfd].events = POLLIN | POLLOUT | POLLPRI ; 00179 fds[nfd].revents = 0; 00180 00181 nfd++; 00182 fds[nfd].fd = _fdunlock[1]; 00183 fds[nfd].events = POLLIN | POLLOUT | POLLPRI ; 00184 fds[nfd].revents = 0; 00185 } 00186 00187 _mutex_w.unlock(); 00188 00189 int wait_min = 10000; 00190 00191 DefaultTimeouts::iterator ti; 00192 00193 _mutex_t.lock(); 00194 00195 for (ti = _timeouts.begin(); ti != _timeouts.end(); ++ti) 00196 { 00197 if ((*ti)->enabled() && (*ti)->interval() < wait_min) 00198 wait_min = (*ti)->interval(); 00199 } 00200 00201 _mutex_t.unlock(); 00202 00203 poll(fds, nfd, wait_min); 00204 00205 timeval now; 00206 gettimeofday(&now, NULL); 00207 00208 double now_millis = millis(now); 00209 00210 _mutex_t.lock(); 00211 00212 ti = _timeouts.begin(); 00213 00214 while (ti != _timeouts.end()) 00215 { 00216 DefaultTimeouts::iterator tmp = ti; 00217 ++tmp; 00218 00219 if ((*ti)->enabled() && now_millis >= (*ti)->_expiration) 00220 { 00221 (*ti)->expired(*(*ti)); 00222 00223 if ((*ti)->_repeat) 00224 { 00225 (*ti)->_expiration = now_millis + (*ti)->_interval; 00226 } 00227 00228 } 00229 00230 ti = tmp; 00231 } 00232 00233 _mutex_t.unlock(); 00234 00235 _mutex_w.lock(); 00236 00237 for (int j = 0; j < nfd; ++j) 00238 { 00239 DefaultWatches::iterator wi; 00240 00241 for (wi = _watches.begin(); wi != _watches.end();) 00242 { 00243 DefaultWatches::iterator tmp = wi; 00244 ++tmp; 00245 00246 if ((*wi)->enabled() && (*wi)->_fd == fds[j].fd) 00247 { 00248 if (fds[j].revents) 00249 { 00250 (*wi)->_state = fds[j].revents; 00251 00252 (*wi)->ready(*(*wi)); 00253 00254 fds[j].revents = 0; 00255 } 00256 } 00257 00258 wi = tmp; 00259 } 00260 } 00261 _mutex_w.unlock(); 00262 } 00263