summaryrefslogtreecommitdiffstats
path: root/qtmcop
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-05 00:01:18 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-05 00:01:18 +0000
commit42995d7bf396933ee60c5f89c354ea89cf13df0d (patch)
treecfdcea0ac57420e7baf570bfe435e107bb842541 /qtmcop
downloadarts-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.am14
-rw-r--r--qtmcop/qiomanager.cc299
-rw-r--r--qtmcop/qiomanager.h106
-rw-r--r--qtmcop/qiomanager_p.h77
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