diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-05 00:01:18 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-05 00:01:18 +0000 |
commit | 42995d7bf396933ee60c5f89c354ea89cf13df0d (patch) | |
tree | cfdcea0ac57420e7baf570bfe435e107bb842541 /qtmcop | |
download | arts-42995d7bf396933ee60c5f89c354ea89cf13df0d.tar.gz arts-42995d7bf396933ee60c5f89c354ea89cf13df0d.zip |
Copy of aRts for Trinity modifications
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/dependencies/arts@1070145 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'qtmcop')
-rw-r--r-- | qtmcop/Makefile.am | 14 | ||||
-rw-r--r-- | qtmcop/qiomanager.cc | 299 | ||||
-rw-r--r-- | qtmcop/qiomanager.h | 106 | ||||
-rw-r--r-- | qtmcop/qiomanager_p.h | 77 |
4 files changed, 496 insertions, 0 deletions
diff --git a/qtmcop/Makefile.am b/qtmcop/Makefile.am new file mode 100644 index 0000000..74f638a --- /dev/null +++ b/qtmcop/Makefile.am @@ -0,0 +1,14 @@ +lib_LTLIBRARIES = libqtmcop.la + +INCLUDES = -I$(top_srcdir)/mcop -I$(top_builddir)/mcop $(all_includes) $(QT_INCLUDES) +KDE_OPTIONS = qtonly + +libqtmcop_la_SOURCES = qiomanager.cc +libqtmcop_la_LIBADD = $(top_builddir)/mcop/libmcop.la $(LIB_QT) +libqtmcop_la_LDFLAGS = -no-undefined -version-info 1:0 $(KDE_RPATH) \ + $(KDE_MT_LDFLAGS) $(QT_LDFLAGS) $(USER_LDFLAGS) $(X_LDFLAGS) $(LDFLAGS_AS_NEEDED) + +METASOURCES = qiomanager_p.moc + +artsincludedir = $(includedir)/arts +artsinclude_HEADERS = qiomanager.h diff --git a/qtmcop/qiomanager.cc b/qtmcop/qiomanager.cc new file mode 100644 index 0000000..c49d83c --- /dev/null +++ b/qtmcop/qiomanager.cc @@ -0,0 +1,299 @@ + /* + + Copyright (C) 1999-2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "qiomanager.h" +#include "qiomanager_p.h" +#include <qsocketnotifier.h> +#include <qapplication.h> +#include "debug.h" +#include "dispatcher.h" +#include "thread.h" + +using namespace std; +using namespace Arts; + +/* + * Collected incompatibilities of QIOManager (compared against StdIOManager): + * + * - StdIOManager catches up timers (i.e. if a 100ms timer hasn't been + * notified for half a second, it will get notified five times to + * catch up the lost time + * - StdIOManager is able to watch the same filedescriptor twice for reading + * - StdIOManager sends notifications soon after they have been produced, + * whereas we use a hackish 50ms timer to deliver them + */ + +/* + * Fallback for the case where we should perform blocking + */ +namespace Arts { +class QIOManagerBlocking : public StdIOManager { +public: + void setLevel(int newLevel) { level = newLevel; } +}; +} + +/* + * QIOManager is a singleton (or at least supposed to be used only once at + * most, and the behaviour would pretty undefined if you violate this), so we + * use static variables for private data here. + */ +static int qioLevel; +static QIOManager *qioManager = 0; +static QIOManagerBlocking *qioManagerBlocking = 0; +static bool qioBlocking; + +/* + * QIOWatch: + */ +QIOWatch::QIOWatch(int fd, int type, IONotify *notify, + QSocketNotifier::Type qtype, bool reentrant) + : _fd(fd), _type(type), _client(notify), _reentrant(reentrant) +{ + qsocketnotify = new QSocketNotifier(fd,qtype,this); + connect(qsocketnotify,SIGNAL(activated(int)),this,SLOT(notify(int))); +} + +void QIOWatch::notify(int socket) +{ + arts_assert(socket == _fd); + qioManager->dispatch(this); +} + +/* + * QTimeWatch: + */ +QTimeWatch::QTimeWatch(int milliseconds, TimeNotify *notify) +{ + timer = new QTimer(this); + connect( timer, SIGNAL(timeout()), this, SLOT(notify()) ); + timer->start(milliseconds); + _client = notify; +} + +void QTimeWatch::notify() +{ + qioManager->dispatch(this); +} + +/* + * Handle NotificationManager::the()->run() from time to time + */ +namespace Arts { + +class HandleNotifications : public TimeNotify { +public: + void notifyTime() + { + Arts::Dispatcher::the()->ioManager()->removeTimer(this); + NotificationManager::the()->run(); + delete this; + } +}; +} + +/* + * QIOManager: + */ +QIOManager::QIOManager() +{ + assert(!qioManager); + qioManager = this; + qioLevel = 0; + qioBlocking = true; + qioManagerBlocking = new QIOManagerBlocking(); +} + +QIOManager::~QIOManager() +{ + assert(qioManager); + qioManager = 0; + + delete qioManagerBlocking; + qioManagerBlocking = 0; +} + +void QIOManager::processOneEvent(bool blocking) +{ + assert(SystemThreads::the()->isMainThread()); + + if(qioBlocking) + { + qioLevel++; + if(qioLevel == 1) + Dispatcher::lock(); + + /* + * we explicitly take the level to qioManagerBlocking, so that it + * will process reentrant watchFDs only + */ + qioManagerBlocking->setLevel(qioLevel); + qioManagerBlocking->processOneEvent(blocking); + + if(qioLevel == 1) + Dispatcher::unlock(); + qioLevel--; + } + else + { + if(blocking) + qApp->processOneEvent(); + else + qApp->processEvents(0); + } +} + +void QIOManager::run() +{ + arts_warning("QIOManager::run() not implemented."); +} + +void QIOManager::terminate() +{ + arts_warning("QIOManager::terminate() not implemented."); +} + +void QIOManager::watchFD(int fd, int types, IONotify *notify) +{ + bool r = (types & IOType::reentrant) != 0; + + if(types & IOType::read) + { + fdList.push_back( + new QIOWatch(fd, IOType::read, notify, QSocketNotifier::Read, r) + ); + } + if(types & IOType::write) + { + fdList.push_back( + new QIOWatch(fd, IOType::write, notify, QSocketNotifier::Write, r) + ); + } + if(types & IOType::except) + { + fdList.push_back( + new QIOWatch(fd, IOType::except, notify, QSocketNotifier::Exception, + r) + ); + } + if(r) qioManagerBlocking->watchFD(fd, types, notify); +} + +void QIOManager::remove(IONotify *notify, int types) +{ + list<QIOWatch *>::iterator i; + + i = fdList.begin(); + while(i != fdList.end()) + { + QIOWatch *w = *i; + + if(w->type() & types && w->client() == notify) + { + delete w; + fdList.erase(i); + i = fdList.begin(); + } + else i++; + } + qioManagerBlocking->remove(notify, types); +} + +void QIOManager::addTimer(int milliseconds, TimeNotify *notify) +{ + if (milliseconds == -1 && notify == 0) + { + // HACK: in order to not add a virtual function to IOManager we're calling addTimer with + // magic values. This call tells the ioManager that notifications are pending and + // NotificationManager::run() should get called soon. + notify = new HandleNotifications(); + milliseconds = 0; + } + timeList.push_back(new QTimeWatch(milliseconds,notify)); +} + +void QIOManager::removeTimer(TimeNotify *notify) +{ + list<QTimeWatch *>::iterator i; + + i = timeList.begin(); + while(i != timeList.end()) + { + QTimeWatch *w = *i; + + if(w->client() == notify) + { + delete w; + timeList.erase(i); + i = timeList.begin(); + } + else i++; + } +} + +void QIOManager::dispatch(QIOWatch *ioWatch) +{ + qioLevel++; + if(qioLevel == 1) + Dispatcher::lock(); + + /* + * FIXME: there is main loop pollution for (qioBlocking == false) here: + * + * As QIOManager will never disable the socket notifiers that are not + * to be carried out reentrant, these will (maybe) fire again and again, + * so that CPU is wasted. + */ + if(qioLevel == 1 || ioWatch->reentrant()) + ioWatch->client()->notifyIO(ioWatch->fd(),ioWatch->type()); + + if(qioLevel == 1) + Dispatcher::unlock(); + qioLevel--; +} + +void QIOManager::dispatch(QTimeWatch *timeWatch) +{ + qioLevel++; + if(qioLevel == 1) + Dispatcher::lock(); + + // timers are never done reentrant + if(qioLevel == 1) + timeWatch->client()->notifyTime(); + + if(qioLevel == 1) + Dispatcher::unlock(); + qioLevel--; +} + +bool QIOManager::blocking() +{ + return qioBlocking; +} + +void QIOManager::setBlocking(bool blocking) +{ + qioBlocking = blocking; +} + +#include "qiomanager_p.moc" diff --git a/qtmcop/qiomanager.h b/qtmcop/qiomanager.h new file mode 100644 index 0000000..7bef332 --- /dev/null +++ b/qtmcop/qiomanager.h @@ -0,0 +1,106 @@ + /* + + Copyright (C) 1999-2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +/* + * BC - Status (2002-03-08): QIOManager. + * + * QIOManager is kept binary compatible. + */ + +#ifndef QIOMANAGER_H +#define QIOMANAGER_H + +#include "iomanager.h" +#include <qobject.h> +#include <qtimer.h> +#include <qsocketnotifier.h> +#include <list> +#include "arts_export.h" + +namespace Arts { + +class QIOWatch; +class QTimeWatch; + +/** + * QIOManager performs MCOP I/O inside the Qt event loop. This way, you will + * be able to receive requests and notifications inside Qt application. The + * usual way to set it up is: + * + * <pre> + * KApplication app(argc, argv); // as usual + * + * Arts::QIOManager qiomanager; + * Arts::Dispatcher dispatcher(&qiomanager); + * ... + * return app.exec(); // as usual + * </pre> + */ + +class ARTS_EXPORT QIOManager : public IOManager { +protected: + friend class QIOWatch; + friend class QTimeWatch; + + std::list<QIOWatch *> fdList; + std::list<QTimeWatch *> timeList; + + void dispatch(QIOWatch *ioWatch); + void dispatch(QTimeWatch *timeWatch); + +public: + QIOManager(); + ~QIOManager(); + + void processOneEvent(bool blocking); + void run(); + void terminate(); + void watchFD(int fd, int types, IONotify *notify); + void remove(IONotify *notify, int types); + void addTimer(int milliseconds, TimeNotify *notify); + void removeTimer(TimeNotify *notify); + + /** + * This controls what QIOManager will do while waiting for the result + * of an MCOP request, the possibilities are: + * + * @li block until the request is completed (true) + * @li open a local event loop (false) + * + * It is much easier to write working and reliable code with blocking + * enabled, so this is the default. If you disable blocking, you have + * to deal with the fact that timers, user interaction and similar + * "unpredictable" things will possibly influence your code in all + * places where you make a remote MCOP call (which is quite often in + * MCOP applications). + */ + void setBlocking(bool blocking); + + /** + * Query whether blocking is enabled. + */ + bool blocking(); +}; + +} + +#endif diff --git a/qtmcop/qiomanager_p.h b/qtmcop/qiomanager_p.h new file mode 100644 index 0000000..78cdbdc --- /dev/null +++ b/qtmcop/qiomanager_p.h @@ -0,0 +1,77 @@ + /* + + Copyright (C) 1999-2001 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +/* + * BC - Status (2002-03-08): QIOWatch, QTimeWatch. + * + * These classes provide implementation details and not meant to be used + * in any way. + */ + +#ifndef QIOMANAGER_P_H +#define QIOMANAGER_P_H + +#include "iomanager.h" +#include <qobject.h> +#include <qtimer.h> +#include <qsocketnotifier.h> +#include <list> + +namespace Arts { + +class QIOWatch : public QObject { + Q_OBJECT +protected: + QSocketNotifier *qsocketnotify; + int _fd; + int _type; + IONotify *_client; + bool _reentrant; + +public: + QIOWatch(int fd, int type, IONotify *notify, QSocketNotifier::Type qtype, + bool reentrant); + + inline IONotify *client() { return _client; } + inline int type() { return _type; } + inline int fd() { return _fd; } + inline bool reentrant() { return _reentrant; } +public slots: + void notify(int socket); +}; + +class QTimeWatch : public QObject { + Q_OBJECT +protected: + QTimer *timer; + TimeNotify *_client; +public: + QTimeWatch(int milliseconds, TimeNotify *notify); + + inline TimeNotify *client() { return _client; } +public slots: + void notify(); +}; + +} + +#endif |