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