~ubuntu-branches/ubuntu/trusty/kvirc/trusty

« back to all changes in this revision

Viewing changes to src/kvilib/system/kvi_thread.h

  • Committer: Bazaar Package Importer
  • Author(s): Kai Wasserbäch, Kai Wasserbäch, Raúl Sánchez Siles
  • Date: 2011-02-12 10:40:21 UTC
  • mfrom: (14.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110212104021-5mh4f75jlku20mnt
The combined "Twisted Experiment" and "Nocturnal Raid" release.

[ Kai Wasserbäch ]
* Synced to upstream's SVN revision 5467.
* debian/rules:
  - Added .PHONY line.
  - Resurrect -DMANUAL_REVISION, got lost somewhere and we build SVN
    revisions again.
  - Replace "-DWITH_NO_EMBEDDED_CODE=YES" with "-DWANT_CRYPTOPP=YES".
  - Change the remaining -DWITH/-DWITHOUT to the new -DWANT syntax.
* debian/control:
  - Removed DMUA, I'm a DD now.
  - Changed my e-mail address.
  - Removed unneeded relationships (no upgrades over two releases are
    supported).
  - Fix Suggests for kvirc-dbg.
  - kvirc-data: Make the "Suggests: kvirc" a Recommends, doesn't make much
    sense to install the -data package without the program.
* debian/source/local-options: Added with "unapply-patches".
* debian/kvirc.lintian-overrides: Updated to work for 4.1.1.
* debian/patches/21_make_shared-mime-info_B-D_superfluous.patch: Updated.
* debian/kvirc-data.install: Added .notifyrc.

[ Raúl Sánchez Siles ]
* Stating the right version where kvirc-data break and replace should happen.
* Fixing link to license file.
* Added French and Portuguese man pages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#ifndef _KVI_THREAD_H_
2
 
#define _KVI_THREAD_H_
3
 
//=============================================================================
4
 
//
5
 
//   File : kvi_thread.h
6
 
//   Creation date : Mon May 17 1999 04:26:41 CEST by Szymon Stefanek
7
 
//
8
 
//   This file is part of the KVirc irc client distribution
9
 
//   Copyright (C) 1999-2008 Szymon Stefanek (pragma at kvirc dot net)
10
 
//
11
 
//   This program is FREE software. You can redistribute it and/or
12
 
//   modify it under the terms of the GNU General Public License
13
 
//   as published by the Free Software Foundation; either version 2
14
 
//   of the License, or (at your opinion) any later version.
15
 
//
16
 
//   This program is distributed in the HOPE that it will be USEFUL,
17
 
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
 
//   See the GNU General Public License for more details.
20
 
//
21
 
//   You should have received a copy of the GNU General Public License
22
 
//   along with this program. If not, write to the Free Software Foundation,
23
 
//   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24
 
//
25
 
//=============================================================================
26
 
 
27
 
#include "kvi_settings.h"
28
 
#include "kvi_heapobject.h"
29
 
#include "kvi_string.h"
30
 
 
31
 
#include <QObject>
32
 
#include <QSocketNotifier>
33
 
#include "kvi_pointerlist.h"
34
 
#include <QEvent>
35
 
 
36
 
 
37
 
//
38
 
// Simple thread implementation
39
 
// This is enough for KVIrc needs
40
 
// HANDLE WITH CARE
41
 
//
42
 
 
43
 
 
44
 
// Portability stuff
45
 
 
46
 
#if defined(COMPILE_ON_WINDOWS) || defined(COMPILE_ON_MINGW)
47
 
 
48
 
        #include <winsock2.h> // this will pull in windows.h and will avoid windock.h inclusion
49
 
        //#include <windows.h>
50
 
        // Windoze thread abstraction layer
51
 
        #define kvi_mutex_t HANDLE
52
 
        inline void kvi_threadMutexInit(kvi_mutex_t * _pMutex_t)
53
 
        {
54
 
                *_pMutex_t = CreateMutex(0,0,NULL);
55
 
        }
56
 
        #define kvi_threadMutexLock(_pMutex_t) WaitForSingleObject(*_pMutex_t,INFINITE)
57
 
        #define kvi_threadMutexUnlock(_pMutex_t) ReleaseMutex(*_pMutex_t)
58
 
        #define kvi_threadMutexDestroy(_pMutex_t) CloseHandle(*_pMutex_t)
59
 
        inline bool kvi_threadMutexTryLock(kvi_mutex_t *_pMutex_t)
60
 
        {
61
 
                return (WaitForSingleObject(*_pMutex_t,0) == WAIT_OBJECT_0);
62
 
        }
63
 
 
64
 
        #define kvi_thread_t HANDLE
65
 
 
66
 
        inline bool kvi_threadCreate(kvi_thread_t *t,LPTHREAD_START_ROUTINE start_routine,void * arg)
67
 
        {
68
 
                DWORD dwThreadId;
69
 
                *t = CreateThread(NULL,0,start_routine,arg,0,&dwThreadId);
70
 
                return (*t != NULL);
71
 
        }
72
 
 
73
 
        #define kvi_threadExit() ExitThread(0)
74
 
 
75
 
#else
76
 
        #ifdef COMPILE_THREADS_USE_POSIX
77
 
                // Glibc pthread implementation
78
 
 
79
 
                #include <pthread.h>
80
 
                #include <errno.h> // for EBUSY
81
 
 
82
 
                // Mutex stuff
83
 
                #define kvi_mutex_t pthread_mutex_t
84
 
                #define kvi_threadMutexInit(_pMutex_t) pthread_mutex_init(_pMutex_t,0)
85
 
                #define kvi_threadMutexLock(_pMutex_t) pthread_mutex_lock(_pMutex_t)
86
 
                #define kvi_threadMutexUnlock(_pMutex_t) pthread_mutex_unlock(_pMutex_t)
87
 
                #define kvi_threadMutexDestroy(_pMutex_t) pthread_mutex_destroy(_pMutex_t)
88
 
                inline bool kvi_threadMutexTryLock(kvi_mutex_t *_pMutex_t)
89
 
                {
90
 
                        return (pthread_mutex_trylock(_pMutex_t) != EBUSY);
91
 
                }
92
 
                // Actually unused
93
 
                // #define kvi_threadMutexTryLock(_pMutex_t) pthread_mutex_trylock(_pMutex_t)
94
 
 
95
 
                // Thread stuff
96
 
                #define kvi_thread_t pthread_t
97
 
 
98
 
                inline bool kvi_threadCreate(kvi_thread_t *t,void * (*start_routine)(void *),void * arg)
99
 
                {
100
 
                        pthread_attr_t a;
101
 
                        pthread_attr_init(&a);
102
 
                        pthread_attr_setinheritsched(&a,PTHREAD_INHERIT_SCHED);
103
 
                        pthread_attr_setdetachstate(&a,PTHREAD_CREATE_DETACHED);
104
 
 
105
 
                        int ret = pthread_create(t,&a,start_routine,arg);
106
 
 
107
 
                        pthread_attr_destroy(&a);
108
 
                        return (ret == 0);
109
 
                }
110
 
 
111
 
                // We don't care about exit codes at all
112
 
                #define kvi_threadExit() pthread_exit(0)
113
 
        #else
114
 
                #ifdef COMPILE_THREADS_USE_SOLARIS_LIBTHREAD
115
 
                        // Native solaris implementation
116
 
                        #include <thread.h>
117
 
                        #include <synch.h>
118
 
                        #include <errno.h>
119
 
 
120
 
                        // Mutex stuff
121
 
                        #define kvi_mutex_t mutex_t
122
 
                        #define kvi_threadMutexInit(_pMutex_t) mutex_init(_pMutex_t,0,0)
123
 
                        #define kvi_threadMutexLock(_pMutex_t) mutex_lock(_pMutex_t)
124
 
                        #define kvi_threadMutexUnlock(_pMutex_t) mutex_unlock(_pMutex_t)
125
 
                        #define kvi_threadMutexDestroy(_pMutex_t) mutex_destroy(_pMutex_t)
126
 
                        inline bool kvi_threadMutexTryLock(kvi_mutex_t *_pMutex_t)
127
 
                        {
128
 
                                return (mutex_trylock(_pMutex_t) != EBUSY);
129
 
                        };
130
 
                        // Actually unused
131
 
                        // #define kvi_threadMutexTryLock(_pMutex_t) mutex_trylock(_pMutex_t)
132
 
 
133
 
                        // Thread stuff
134
 
                        #define kvi_thread_t thread_t
135
 
 
136
 
                        inline bool kvi_threadCreate(kvi_thread_t *t,void * (*start_routine)(void *),void *arg)
137
 
                        {
138
 
                                return (thr_create(0,0,start_routine,arg,THR_DETACHED,t) == 0);
139
 
                        }
140
 
 
141
 
                        // We don't care about exit codes at all
142
 
                        #define kvi_threadExit() thr_exit(0)
143
 
                #else
144
 
// FIXME:                       #warning "Missing a decent thread implementation: we're going to fail , sorry!"
145
 
                #endif
146
 
        #endif
147
 
#endif
148
 
 
149
 
class KVILIB_API KviMutex : public KviHeapObject
150
 
{
151
 
private:
152
 
        kvi_mutex_t m_mutex;
153
 
#if defined(COMPILE_ON_WINDOWS) || defined(COMPILE_ON_MINGW)
154
 
        bool        m_bLocked;
155
 
#endif
156
 
public:
157
 
        KviMutex(){ kvi_threadMutexInit(&m_mutex); };
158
 
        virtual ~KviMutex(){ kvi_threadMutexDestroy(&m_mutex); };
159
 
public:
160
 
#if defined(COMPILE_ON_WINDOWS) || defined(COMPILE_ON_MINGW)
161
 
        void lock(){ kvi_threadMutexLock(&m_mutex); m_bLocked = true; };
162
 
        void unlock(){ m_bLocked = false; kvi_threadMutexUnlock(&m_mutex); };
163
 
        bool locked(){ return m_bLocked; };
164
 
#else
165
 
        void lock(){ kvi_threadMutexLock(&m_mutex); };
166
 
        void unlock(){ kvi_threadMutexUnlock(&m_mutex); };
167
 
        bool locked();
168
 
#endif
169
 
};
170
 
 
171
 
 
172
 
// simple thread class implementation
173
 
// this is also called "Blind" thread class
174
 
 
175
 
class KVILIB_API KviThread : public KviHeapObject
176
 
{
177
 
public:
178
 
        KviThread();
179
 
        virtual ~KviThread();
180
 
private:
181
 
        kvi_thread_t    m_thread;
182
 
        bool            m_bRunning;
183
 
        bool            m_bStartingUp;
184
 
        KviMutex      * m_pRunningMutex;
185
 
        KviPointerList<QEvent> * m_pLocalEventQueue;
186
 
public:
187
 
        // public KviThread interface
188
 
        // HANDLE WITH CARE
189
 
 
190
 
        // Runs the thread...call only from external threads!!! :)
191
 
        // This function returns true if the child thread has been successfully created
192
 
        // this des not mean that run() is being already executed...
193
 
        // isStartingUp() will return true from this moment until
194
 
        // the child thread jumps into run() where it will be set to running state (isRunning() == true)
195
 
        // and removed from startingUp state.
196
 
        bool start();
197
 
        // Returns the state of the thread...safe to call from anywhere
198
 
        bool isRunning();
199
 
        // Returns the state of the thread...safe to call from anywhere
200
 
        bool isStartingUp(); // start() called , but not in run() yet...
201
 
        // Waits for the termination of this thread: call only from external threads!!! :)
202
 
        void wait();
203
 
        // DO NOT TOUCH THIS ONE!
204
 
        void internalThreadRun_doNotTouchThis();
205
 
 
206
 
        static void sleep(unsigned long sec);
207
 
        static void msleep(unsigned long msec);
208
 
        static void usleep(unsigned long usec);
209
 
protected:
210
 
        // protected KviThread interface
211
 
        // HANDLE WITH CARE TOO!
212
 
 
213
 
        // Reimplement this with your job
214
 
        virtual void run(){};
215
 
        // Terminates the execution of the calling thread
216
 
        void exit();
217
 
        // The tricky part: threadsafe event dispatching
218
 
        // Slave thread -> main thread objects
219
 
        void postEvent(QObject *o,QEvent *e);
220
 
private:
221
 
        void setRunning(bool bRunning);
222
 
        void setStartingUp(bool bStartingUp);
223
 
};
224
 
 
225
 
// QEvent::Type for Thread events
226
 
#define KVI_THREAD_EVENT (((int)QEvent::User) + 2000)
227
 
 
228
 
// CONSTANTS FOR KviThreadEvent::eventId();
229
 
 
230
 
///////////////////////////////////////////////////////////////
231
 
// extern -> slave thread
232
 
 
233
 
// Your reimplementation of KviSensitiveThread MUST handle this
234
 
// and exit when this event is received
235
 
 
236
 
// Terminate is a plain KviThreadEvent
237
 
#define KVI_THREAD_EVENT_TERMINATE 0
238
 
 
239
 
///////////////////////////////////////////////////////////////
240
 
// slave thread -> master object
241
 
 
242
 
// The following standard events are sent from the thread to the master object
243
 
 
244
 
// The following are plain KviThreadEvent objects
245
 
#define KVI_THREAD_EVENT_SUCCESS 100
246
 
 
247
 
// The following are KviThreadDataEvent<int>
248
 
#define KVI_THREAD_EVENT_STATECHANGE 150
249
 
 
250
 
// The following are KviThreadDataEvent<KviStr>
251
 
#define KVI_THREAD_EVENT_MESSAGE 200
252
 
#define KVI_THREAD_EVENT_WARNING 201
253
 
#define KVI_THREAD_EVENT_ERROR 202
254
 
#define KVI_THREAD_EVENT_DATA 203
255
 
 
256
 
// The following is KviThreadDataEvent<KviDataBuffer>
257
 
#define KVI_THREAD_EVENT_BINARYDATA 300
258
 
 
259
 
// The user events
260
 
#define KVI_THREAD_USER_EVENT_BASE 1000
261
 
 
262
 
// #warning "Get rid of the m_szMessage member of KviThreadEvent : eventual data should be passed with a KviThreadDataEvent"
263
 
 
264
 
// Base class for all thread events
265
 
class KVILIB_API KviThreadEvent : public QEvent, public KviHeapObject
266
 
{
267
 
protected:
268
 
        int         m_eventId;
269
 
        KviThread * m_pSender;
270
 
public:
271
 
        KviThreadEvent(int evId,KviThread * sender = 0)
272
 
                : QEvent((QEvent::Type)KVI_THREAD_EVENT) , m_eventId(evId) , m_pSender(sender) {};
273
 
        virtual ~KviThreadEvent(){};
274
 
public:
275
 
        // This is the sender of the event
276
 
        // WARNING : this MAY be null , threads CAN send anonymous events
277
 
        KviThread * sender(){ return m_pSender; };
278
 
        int id(){ return m_eventId; };
279
 
};
280
 
 
281
 
template<class TData> class KviThreadDataEvent : public KviThreadEvent
282
 
{
283
 
protected:
284
 
        TData * m_pData;
285
 
public:
286
 
        KviThreadDataEvent(int evId,TData * pData = 0,KviThread * sender = 0)
287
 
                : KviThreadEvent(evId,sender){ m_pData = pData; };
288
 
        virtual ~KviThreadDataEvent(){ if(m_pData)delete m_pData; };
289
 
public:
290
 
        void setData(TData * d){ if(m_pData)delete m_pData; m_pData = d; };
291
 
        TData * getData(){ TData * aux = m_pData; m_pData = 0; return aux; };
292
 
        TData * data(){ return m_pData; };
293
 
};
294
 
 
295
 
// A thread that has also an internal event queue
296
 
// so events can be posted from the master side to the slave one
297
 
// Reimplementations of this class should periodically check
298
 
// dequeueEvent() and eventually process the incoming events (and then DELETE it)
299
 
 
300
 
// KVI_THREAD_EVENT_TERMINATE should be always handled by the reimplementation
301
 
// and it should always exit (cleanly) when this event is received
302
 
 
303
 
 
304
 
class KVILIB_API KviSensitiveThread : public KviThread
305
 
{
306
 
public:
307
 
        KviSensitiveThread();
308
 
        virtual ~KviSensitiveThread();
309
 
protected:
310
 
        KviMutex              * m_pLocalEventQueueMutex;
311
 
        KviPointerList<KviThreadEvent> * m_pLocalEventQueue;
312
 
public:
313
 
        // enqueues an event directed to THIS thread
314
 
        // the event must be allocated with NEW and
315
 
        // will be destroyed on the slave side
316
 
        void enqueueEvent(KviThreadEvent *e);
317
 
        // enqueues a terminate event and waits() for the slave thread
318
 
        // the slave thread MUST handle KVI_THREAD_EVENT_TERMINATE
319
 
        void terminate();
320
 
protected:
321
 
        // slave side:
322
 
        // returns the first event in the local queue
323
 
        // the event MUST BE DELETED after processing
324
 
        KviThreadEvent * dequeueEvent();
325
 
};
326
 
 
327
 
// =============================================================================================//
328
 
// This is private stuff...only KviThread and KviApp may use it
329
 
// and may call only specific functions...don't touch.
330
 
 
331
 
typedef struct _KviThreadPendingEvent
332
 
{
333
 
        QObject *o;
334
 
        QEvent *e;
335
 
} KviThreadPendingEvent;
336
 
 
337
 
class KVILIB_API KviThreadManager : public QObject
338
 
{
339
 
        friend class KviApp;
340
 
        friend class KviThread;
341
 
        Q_OBJECT
342
 
protected:
343
 
        // These should be private...but we don't want anyone to complain
344
 
        // Treat as private plz.
345
 
        KviThreadManager();
346
 
        ~KviThreadManager();
347
 
public:
348
 
        static void killPendingEvents(QObject * receiver);
349
 
private:
350
 
#if !defined(COMPILE_ON_WINDOWS) && !defined(COMPILE_ON_MINGW)
351
 
        QSocketNotifier * m_pSn;
352
 
#endif
353
 
        KviMutex * m_pMutex; // This class performs only atomic operations
354
 
        KviPointerList<KviThread> * m_pThreadList;
355
 
        int m_iWaitingThreads;
356
 
#if !defined(COMPILE_ON_WINDOWS) && !defined(COMPILE_ON_MINGW)
357
 
        KviPointerList<KviThreadPendingEvent> * m_pEventQueue;
358
 
        int m_fd[2];
359
 
        int m_iTriggerCount;
360
 
#endif
361
 
protected:
362
 
        // Public to KviThread only
363
 
        void registerSlaveThread(KviThread *t);
364
 
        void unregisterSlaveThread(KviThread *t);
365
 
 
366
 
        void threadEnteredWaitState();
367
 
        void threadLeftWaitState();
368
 
 
369
 
        void postSlaveEvent(QObject *o,QEvent *e);
370
 
        void killPendingEventsByReceiver(QObject * receiver);
371
 
        // Public to KviApp only
372
 
        static void globalInit();
373
 
        static void globalDestroy();
374
 
private slots:
375
 
        void eventsPending(int fd);
376
 
};
377
 
 
378
 
 
379
 
#endif //!_KVI_THREAD_H_