From 42995d7bf396933ee60c5f89c354ea89cf13df0d Mon Sep 17 00:00:00 2001 From: tpearson Date: Tue, 5 Jan 2010 00:01:18 +0000 Subject: 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 --- qtmcop/Makefile.am | 14 +++ qtmcop/qiomanager.cc | 299 ++++++++++++++++++++++++++++++++++++++++++++++++++ qtmcop/qiomanager.h | 106 ++++++++++++++++++ qtmcop/qiomanager_p.h | 77 +++++++++++++ 4 files changed, 496 insertions(+) create mode 100644 qtmcop/Makefile.am create mode 100644 qtmcop/qiomanager.cc create mode 100644 qtmcop/qiomanager.h create mode 100644 qtmcop/qiomanager_p.h (limited to 'qtmcop') 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 +#include +#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::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::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 +#include +#include +#include +#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: + * + *
+ * KApplication app(argc, argv);    // as usual
+ *
+ * Arts::QIOManager qiomanager;
+ * Arts::Dispatcher dispatcher(&qiomanager);
+ * ...
+ * return app.exec();               // as usual
+ * 
+ */ + +class ARTS_EXPORT QIOManager : public IOManager { +protected: + friend class QIOWatch; + friend class QTimeWatch; + + std::list fdList; + std::list 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 +#include +#include +#include + +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 -- cgit v1.2.1