1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #ifndef QEVENTDISPATCHER_UNIX_P_H
43 #define QEVENTDISPATCHER_UNIX_P_H
44 
45 //
46 //  W A R N I N G
47 //  -------------
48 //
49 // This file is not part of the Qt API.  It exists purely as an
50 // implementation detail.  This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55 
56 #include "QtCore/qabstracteventdispatcher.h"
57 #include "QtCore/qlist.h"
58 #include "private/qabstracteventdispatcher_p.h"
59 #include "private/qcore_unix_p.h"
60 #include "private/qpodlist_p.h"
61 #include "QtCore/qvarlengtharray.h"
62 
63 #if !defined(Q_OS_VXWORKS)
64 #  include <sys/time.h>
65 #  if (!defined(Q_OS_HPUX) || defined(__ia64)) && !defined(Q_OS_NACL)
66 #    include <sys/select.h>
67 #  endif
68 #endif
69 
70 QT_BEGIN_NAMESPACE
71 
72 // internal timer info
73 struct QTimerInfo {
74     int id;           // - timer identifier
75     timeval interval; // - timer interval
76     timeval timeout;  // - when to sent event
77     QObject *obj;     // - object to receive event
78     QTimerInfo **activateRef; // - ref from activateTimers
79 };
80 
81 class QTimerInfoList : public QList<QTimerInfo*>
82 {
83 #if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC)) || defined(QT_BOOTSTRAPPED)
84     timeval previousTime;
85     clock_t previousTicks;
86     int ticksPerSecond;
87     int msPerTick;
88 
89     bool timeChanged(timeval *delta);
90 #endif
91 
92     // state variables used by activateTimers()
93     QTimerInfo *firstTimerInfo;
94 
95 public:
96     QTimerInfoList();
97 
98     timeval currentTime;
99     timeval updateCurrentTime();
100 
101     // must call updateCurrentTime() first!
102     void repairTimersIfNeeded();
103 
104     bool timerWait(timeval &);
105     void timerInsert(QTimerInfo *);
106     void timerRepair(const timeval &);
107 
108     void registerTimer(int timerId, int interval, QObject *object);
109     bool unregisterTimer(int timerId);
110     bool unregisterTimers(QObject *object);
111     QList<QPair<int, int> > registeredTimers(QObject *object) const;
112 
113     int activateTimers();
114 };
115 
116 struct QSockNot
117 {
118     QSocketNotifier *obj;
119     int fd;
120     fd_set *queue;
121 };
122 
123 class QSockNotType
124 {
125 public:
126     QSockNotType();
127     ~QSockNotType();
128 
129     typedef QPodList<QSockNot*, 32> List;
130 
131     List list;
132     fd_set select_fds;
133     fd_set enabled_fds;
134     fd_set pending_fds;
135 
136 };
137 
138 class QEventDispatcherUNIXPrivate;
139 
140 class Q_CORE_EXPORT QEventDispatcherUNIX : public QAbstractEventDispatcher
141 {
142     Q_OBJECT
143     Q_DECLARE_PRIVATE(QEventDispatcherUNIX)
144 
145 public:
146     explicit QEventDispatcherUNIX(QObject *parent = 0);
147     ~QEventDispatcherUNIX();
148 
149     bool processEvents(QEventLoop::ProcessEventsFlags flags);
150     bool hasPendingEvents();
151 
152     void registerSocketNotifier(QSocketNotifier *notifier);
153     void unregisterSocketNotifier(QSocketNotifier *notifier);
154 
155     void registerTimer(int timerId, int interval, QObject *object);
156     bool unregisterTimer(int timerId);
157     bool unregisterTimers(QObject *object);
158     QList<TimerInfo> registeredTimers(QObject *object) const;
159 
160     void wakeUp();
161     void interrupt();
162     void flush();
163 
164 protected:
165     QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent = 0);
166 
167     void setSocketNotifierPending(QSocketNotifier *notifier);
168 
169     int activateTimers();
170     int activateSocketNotifiers();
171 
172     virtual int select(int nfds,
173                        fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
174                        timeval *timeout);
175 };
176 
177 class Q_CORE_EXPORT QEventDispatcherUNIXPrivate : public QAbstractEventDispatcherPrivate
178 {
179     Q_DECLARE_PUBLIC(QEventDispatcherUNIX)
180 
181 public:
182     QEventDispatcherUNIXPrivate();
183     ~QEventDispatcherUNIXPrivate();
184 
185     int doSelect(QEventLoop::ProcessEventsFlags flags, timeval *timeout);
186     virtual int initThreadWakeUp();
187     virtual int processThreadWakeUp(int nsel);
188 
189     bool mainThread;
190     int thread_pipe[2];
191 
192     // highest fd for all socket notifiers
193     int sn_highest;
194     // 3 socket notifier types - read, write and exception
195     QSockNotType sn_vec[3];
196 
197     QTimerInfoList timerList;
198 
199     // pending socket notifiers list
200     QSockNotType::List sn_pending_list;
201 
202     QAtomicInt wakeUps;
203     bool interrupt;
204 };
205 
206 QT_END_NAMESPACE
207 
208 #endif // QEVENTDISPATCHER_UNIX_P_H
209