summaryrefslogtreecommitdiff
authorsimon <simon>2002-12-10 11:07:46 (UTC)
committer simon <simon>2002-12-10 11:07:46 (UTC)
commitf468c3bc69655aefa0ec5783405355dd3dde4afc (patch) (unidiff)
treeb358fb36cb4547a0bf2c100573e4846fbc32211c
parent448426777d9e35826898791d03b4bc71335427ff (diff)
downloadopie-f468c3bc69655aefa0ec5783405355dd3dde4afc.zip
opie-f468c3bc69655aefa0ec5783405355dd3dde4afc.tar.gz
opie-f468c3bc69655aefa0ec5783405355dd3dde4afc.tar.bz2
- added ThreadUtil::Thread class
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/multimedia/opieplayer2/threadutil.cpp99
-rw-r--r--noncore/multimedia/opieplayer2/threadutil.h28
2 files changed, 127 insertions, 0 deletions
diff --git a/noncore/multimedia/opieplayer2/threadutil.cpp b/noncore/multimedia/opieplayer2/threadutil.cpp
index 4055c74..5687f42 100644
--- a/noncore/multimedia/opieplayer2/threadutil.cpp
+++ b/noncore/multimedia/opieplayer2/threadutil.cpp
@@ -1,220 +1,319 @@
1/* This file is part of the KDE project 1/* This file is part of the KDE project
2 Copyright (C) 2002 Simon Hausmann <hausmann@kde.org> 2 Copyright (C) 2002 Simon Hausmann <hausmann@kde.org>
3 3
4 This library is free software; you can redistribute it and/or 4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public 5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either 6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version. 7 version 2 of the License, or (at your option) any later version.
8 8
9 This library is distributed in the hope that it will be useful, 9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details. 12 Library General Public License for more details.
13 13
14 You should have received a copy of the GNU Library General Public License 14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to 15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. 17 Boston, MA 02111-1307, USA.
18*/ 18*/
19 19
20#include "threadutil.h" 20#include "threadutil.h"
21 21
22#include <qsocketnotifier.h> 22#include <qsocketnotifier.h>
23 23
24#include <pthread.h> 24#include <pthread.h>
25#include <assert.h> 25#include <assert.h>
26#include <unistd.h> 26#include <unistd.h>
27#include <errno.h>
27 28
28using namespace ThreadUtil; 29using namespace ThreadUtil;
29 30
30struct Mutex::Data 31struct Mutex::Data
31{ 32{
32 Data() 33 Data()
33 { 34 {
34 pthread_mutex_init( &mutex, 0 ); 35 pthread_mutex_init( &mutex, 0 );
35 } 36 }
36 ~Data() 37 ~Data()
37 { 38 {
38 pthread_mutex_destroy( &mutex ); 39 pthread_mutex_destroy( &mutex );
39 } 40 }
40 41
41 pthread_mutex_t mutex; 42 pthread_mutex_t mutex;
42}; 43};
43 44
44Mutex::Mutex() 45Mutex::Mutex()
45 : d( new Data ) 46 : d( new Data )
46{ 47{
47} 48}
48 49
49Mutex::~Mutex() 50Mutex::~Mutex()
50{ 51{
51 delete d; 52 delete d;
52} 53}
53 54
54void Mutex::lock() 55void Mutex::lock()
55{ 56{
56 pthread_mutex_lock( &d->mutex ); 57 pthread_mutex_lock( &d->mutex );
57} 58}
58 59
59void Mutex::unlock() 60void Mutex::unlock()
60{ 61{
61 pthread_mutex_unlock( &d->mutex ); 62 pthread_mutex_unlock( &d->mutex );
62} 63}
63 64
64bool Mutex::tryLock() 65bool Mutex::tryLock()
65{ 66{
66 return pthread_mutex_trylock( &d->mutex ) == 0; 67 return pthread_mutex_trylock( &d->mutex ) == 0;
67} 68}
68 69
69bool Mutex::isLocked() 70bool Mutex::isLocked()
70{ 71{
71 if ( !tryLock() ) 72 if ( !tryLock() )
72 return true; 73 return true;
73 74
74 unlock(); 75 unlock();
75 return false; 76 return false;
76} 77}
77 78
78struct WaitCondition::Data 79struct WaitCondition::Data
79{ 80{
80 Data() 81 Data()
81 { 82 {
82 int result = pthread_cond_init( &waitCondition, 0 ); 83 int result = pthread_cond_init( &waitCondition, 0 );
83 assert( result == 0 ); 84 assert( result == 0 );
84 } 85 }
85 ~Data() 86 ~Data()
86 { 87 {
87 pthread_cond_destroy( &waitCondition ); 88 pthread_cond_destroy( &waitCondition );
88 } 89 }
89 90
90 pthread_cond_t waitCondition; 91 pthread_cond_t waitCondition;
91}; 92};
92 93
93WaitCondition::WaitCondition() 94WaitCondition::WaitCondition()
94 : d( new Data ) 95 : d( new Data )
95{ 96{
96} 97}
97 98
98WaitCondition::~WaitCondition() 99WaitCondition::~WaitCondition()
99{ 100{
100 delete d; 101 delete d;
101} 102}
102 103
103bool WaitCondition::wait() 104bool WaitCondition::wait()
104{ 105{
105 Mutex m; 106 Mutex m;
106 m.lock(); 107 m.lock();
107 return wait( m ); 108 return wait( m );
108} 109}
109 110
110bool WaitCondition::wait( Mutex &mutex ) 111bool WaitCondition::wait( Mutex &mutex )
111{ 112{
112 return pthread_cond_wait( &d->waitCondition, &mutex.d->mutex ); 113 return pthread_cond_wait( &d->waitCondition, &mutex.d->mutex );
113} 114}
114 115
115void WaitCondition::wakeOne() 116void WaitCondition::wakeOne()
116{ 117{
117 pthread_cond_signal( &d->waitCondition ); 118 pthread_cond_signal( &d->waitCondition );
118} 119}
119 120
120void WaitCondition::wakeAll() 121void WaitCondition::wakeAll()
121{ 122{
122 pthread_cond_broadcast( &d->waitCondition ); 123 pthread_cond_broadcast( &d->waitCondition );
123} 124}
124 125
126struct Thread::Data
127{
128 Data() : isRunning( false )
129 {}
130
131 pthread_t self;
132 Mutex guard;
133 bool isRunning;
134
135 WaitCondition finishCondition;
136};
137
138extern "C"
139{
140
141void _threadutil_terminate_thread( void *arg )
142{
143 Thread *thr = ( Thread* )arg;
144
145 assert( thr );
146
147 AutoLock locker( thr->d->guard );
148 thr->d->isRunning = false;
149 thr->d->finishCondition.wakeAll();
150}
151
152void *_threadutil_start_thread( void *arg )
153{
154 Thread *thr = ( Thread* )arg;
155
156 pthread_cleanup_push( _threadutil_terminate_thread, thr );
157
158 thr->d->isRunning = true;
159 thr->run();
160
161 pthread_cleanup_pop( true );
162
163 Thread::exit();
164 return 0; // never reached
165}
166
167}
168
169Thread::Thread()
170 : d( new Data )
171{
172}
173
174Thread::~Thread()
175{
176 assert( d->isRunning == false );
177 delete d;
178}
179
180void Thread::start()
181{
182 AutoLock lock( d->guard );
183
184 if ( d->isRunning ) {
185 qDebug( "ThreadUtil::Thread::start() called for running thread." );
186 return;
187 }
188
189 pthread_attr_t attributes;
190 pthread_attr_init( &attributes );
191 pthread_attr_setscope( &attributes, PTHREAD_SCOPE_SYSTEM );
192 int err = pthread_create( &d->self, &attributes, _threadutil_start_thread, ( void* )this );
193 if ( err != 0 ) {
194 qDebug( "ThreadUtil::Thread::start() : can't create thread: %s", strerror( err ) );
195 pthread_attr_destroy( &attributes );
196 return;
197 }
198 pthread_attr_destroy( &attributes );
199}
200
201void Thread::terminate()
202{
203 AutoLock lock( d->guard );
204 if ( !d->isRunning )
205 return;
206
207 pthread_cancel( d->self );
208}
209
210bool Thread::wait()
211{
212 AutoLock lock( d->guard );
213 if ( !d->isRunning )
214 return true;
215
216 return d->finishCondition.wait( d->guard );
217}
218
219void Thread::exit()
220{
221 pthread_exit( 0 );
222}
223
125OnewayNotifier::OnewayNotifier() 224OnewayNotifier::OnewayNotifier()
126{ 225{
127 int fds[ 2 ]; 226 int fds[ 2 ];
128 pipe( fds ); 227 pipe( fds );
129 m_readFd = fds[ 0 ]; 228 m_readFd = fds[ 0 ];
130 m_writeFd = fds[ 1 ]; 229 m_writeFd = fds[ 1 ];
131 230
132 m_notifier = new QSocketNotifier( m_readFd, QSocketNotifier::Read ); 231 m_notifier = new QSocketNotifier( m_readFd, QSocketNotifier::Read );
133 connect( m_notifier, SIGNAL( activated( int ) ), 232 connect( m_notifier, SIGNAL( activated( int ) ),
134 this, SLOT( wakeUp() ) ); 233 this, SLOT( wakeUp() ) );
135} 234}
136 235
137OnewayNotifier::~OnewayNotifier() 236OnewayNotifier::~OnewayNotifier()
138{ 237{
139 delete m_notifier; 238 delete m_notifier;
140 239
141 ::close( m_readFd ); 240 ::close( m_readFd );
142 ::close( m_writeFd ); 241 ::close( m_writeFd );
143} 242}
144 243
145void OnewayNotifier::notify() 244void OnewayNotifier::notify()
146{ 245{
147 const char c = 42; 246 const char c = 42;
148 ::write( m_writeFd, &c, 1 ); 247 ::write( m_writeFd, &c, 1 );
149} 248}
150 249
151void OnewayNotifier::wakeUp() 250void OnewayNotifier::wakeUp()
152{ 251{
153 char c = 0; 252 char c = 0;
154 253
155 if ( ::read( m_readFd, &c, 1 ) != 1 ) 254 if ( ::read( m_readFd, &c, 1 ) != 1 )
156 return; 255 return;
157 256
158 emit awake(); 257 emit awake();
159} 258}
160 259
161ChannelMessage::ChannelMessage( int type ) 260ChannelMessage::ChannelMessage( int type )
162 : m_type( type ), m_isCall( false ), m_replied( false ), 261 : m_type( type ), m_isCall( false ), m_replied( false ),
163 m_inEventHandler( false ) 262 m_inEventHandler( false )
164{ 263{
165} 264}
166 265
167ChannelMessage::~ChannelMessage() 266ChannelMessage::~ChannelMessage()
168{ 267{
169 if ( m_guard.isLocked() ) 268 if ( m_guard.isLocked() )
170 m_guard.unlock(); 269 m_guard.unlock();
171} 270}
172 271
173void ChannelMessage::reply() 272void ChannelMessage::reply()
174{ 273{
175 if ( !m_isCall ) 274 if ( !m_isCall )
176 { 275 {
177 qDebug( "ChannelMessage::reply() - can't reply oneway message!" ); 276 qDebug( "ChannelMessage::reply() - can't reply oneway message!" );
178 return; 277 return;
179 } 278 }
180 279
181 if ( m_inEventHandler ) 280 if ( m_inEventHandler )
182 { 281 {
183 m_replied = true; 282 m_replied = true;
184 return; 283 return;
185 } 284 }
186 285
187 m_condition.wakeOne(); 286 m_condition.wakeOne();
188 m_guard.unlock(); 287 m_guard.unlock();
189} 288}
190 289
191struct Channel::Private 290struct Channel::Private
192{ 291{
193 Private() 292 Private()
194 { 293 {
195 ownerThread = pthread_self(); 294 ownerThread = pthread_self();
196 } 295 }
197 296
198 pthread_t ownerThread; 297 pthread_t ownerThread;
199}; 298};
200 299
201Channel::Channel( QObject *parent, const char *name ) 300Channel::Channel( QObject *parent, const char *name )
202 : QObject( parent, name ), d( new Private ) 301 : QObject( parent, name ), d( new Private )
203{ 302{
204 connect( &m_notifier, SIGNAL( awake() ), 303 connect( &m_notifier, SIGNAL( awake() ),
205 this, SLOT( deliver() ) ); 304 this, SLOT( deliver() ) );
206} 305}
207 306
208Channel::~Channel() 307Channel::~Channel()
209{ 308{
210 delete d; 309 delete d;
211} 310}
212 311
213void Channel::send( ChannelMessage *message, SendType type ) 312void Channel::send( ChannelMessage *message, SendType type )
214{ 313{
215 if ( type == WaitForReply ) 314 if ( type == WaitForReply )
216 { 315 {
217 message->m_guard.lock(); 316 message->m_guard.lock();
218 message->m_isCall = true; 317 message->m_isCall = true;
219 } 318 }
220 319
diff --git a/noncore/multimedia/opieplayer2/threadutil.h b/noncore/multimedia/opieplayer2/threadutil.h
index 5cc4cdc..b537cc1 100644
--- a/noncore/multimedia/opieplayer2/threadutil.h
+++ b/noncore/multimedia/opieplayer2/threadutil.h
@@ -1,176 +1,204 @@
1/* This file is part of the KDE project 1/* This file is part of the KDE project
2 Copyright (C) 2002 Simon Hausmann <hausmann@kde.org> 2 Copyright (C) 2002 Simon Hausmann <hausmann@kde.org>
3 3
4 This library is free software; you can redistribute it and/or 4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public 5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either 6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version. 7 version 2 of the License, or (at your option) any later version.
8 8
9 This library is distributed in the hope that it will be useful, 9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details. 12 Library General Public License for more details.
13 13
14 You should have received a copy of the GNU Library General Public License 14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to 15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. 17 Boston, MA 02111-1307, USA.
18*/ 18*/
19 19
20#ifndef THREADUTIL_H 20#ifndef THREADUTIL_H
21#define THREADUTIL_H 21#define THREADUTIL_H
22 22
23#include <qvaluelist.h> 23#include <qvaluelist.h>
24#include <qobject.h> 24#include <qobject.h>
25#include <qguardedptr.h> 25#include <qguardedptr.h>
26 26
27class QSocketNotifier; 27class QSocketNotifier;
28 28
29extern "C"
30{
31 void *_threadutil_start_thread( void* );
32 void _threadutil_terminate_thread( void* );
33}
34
29namespace ThreadUtil 35namespace ThreadUtil
30{ 36{
31 37
32 class Mutex 38 class Mutex
33 { 39 {
34 friend class WaitCondition; 40 friend class WaitCondition;
35 public: 41 public:
36 Mutex(); 42 Mutex();
37 ~Mutex(); 43 ~Mutex();
38 44
39 void lock(); 45 void lock();
40 void unlock(); 46 void unlock();
41 bool tryLock(); 47 bool tryLock();
42 bool isLocked(); 48 bool isLocked();
43 49
44 private: 50 private:
45 struct Data; 51 struct Data;
46 Data *d; 52 Data *d;
47 53
48 Mutex( const Mutex & ); 54 Mutex( const Mutex & );
49 Mutex &operator=( const Mutex & ); 55 Mutex &operator=( const Mutex & );
50 }; 56 };
51 57
52 class AutoLock 58 class AutoLock
53 { 59 {
54 public: 60 public:
55 AutoLock( Mutex &mutex ) : m_mutex( mutex ) { m_mutex.lock(); } 61 AutoLock( Mutex &mutex ) : m_mutex( mutex ) { m_mutex.lock(); }
56 ~AutoLock() { m_mutex.unlock(); } 62 ~AutoLock() { m_mutex.unlock(); }
57 63
58 Mutex *operator &() const { return &m_mutex; } 64 Mutex *operator &() const { return &m_mutex; }
59 65
60 private: 66 private:
61 Mutex &m_mutex; 67 Mutex &m_mutex;
62 }; 68 };
63 69
64 class WaitCondition 70 class WaitCondition
65 { 71 {
66 public: 72 public:
67 WaitCondition(); 73 WaitCondition();
68 ~WaitCondition(); 74 ~WaitCondition();
69 75
70 bool wait(); 76 bool wait();
71 bool wait( Mutex &mutex ); 77 bool wait( Mutex &mutex );
72 78
73 void wakeOne(); 79 void wakeOne();
74 void wakeAll(); 80 void wakeAll();
75 81
76 private: 82 private:
77 struct Data; 83 struct Data;
78 Data *d; 84 Data *d;
79 85
80 WaitCondition( const WaitCondition & ); 86 WaitCondition( const WaitCondition & );
81 WaitCondition &operator=( const WaitCondition & ); 87 WaitCondition &operator=( const WaitCondition & );
82 }; 88 };
83 89
90 class Thread
91 {
92 friend void *::_threadutil_start_thread( void* );
93 friend void ::_threadutil_terminate_thread( void* );
94 public:
95 Thread();
96 virtual ~Thread();
97
98 void start();
99 void terminate();
100
101 bool wait();
102
103 static void exit();
104 protected:
105 virtual void run() = 0;
106
107 private:
108 struct Data;
109 Data *d;
110 };
111
84 class OnewayNotifier : public QObject 112 class OnewayNotifier : public QObject
85 { 113 {
86 Q_OBJECT 114 Q_OBJECT
87 public: 115 public:
88 OnewayNotifier(); 116 OnewayNotifier();
89 ~OnewayNotifier(); 117 ~OnewayNotifier();
90 118
91 void notify(); 119 void notify();
92 120
93 signals: 121 signals:
94 void awake(); 122 void awake();
95 123
96 private slots: 124 private slots:
97 void wakeUp(); 125 void wakeUp();
98 126
99 private: 127 private:
100 int m_readFd; 128 int m_readFd;
101 int m_writeFd; 129 int m_writeFd;
102 QSocketNotifier *m_notifier; 130 QSocketNotifier *m_notifier;
103 }; 131 };
104 132
105 133
106 class Channel; 134 class Channel;
107 135
108 class ChannelMessage 136 class ChannelMessage
109 { 137 {
110 friend class Channel; 138 friend class Channel;
111 public: 139 public:
112 ChannelMessage( int type = -1 ); 140 ChannelMessage( int type = -1 );
113 virtual ~ChannelMessage(); 141 virtual ~ChannelMessage();
114 142
115 int type() const { return m_type; } 143 int type() const { return m_type; }
116 144
117 void reply(); 145 void reply();
118 146
119 private: 147 private:
120 ChannelMessage( const ChannelMessage & ); 148 ChannelMessage( const ChannelMessage & );
121 ChannelMessage &operator=( const ChannelMessage ); 149 ChannelMessage &operator=( const ChannelMessage );
122 150
123 int m_type; 151 int m_type;
124 bool m_isCall : 1; 152 bool m_isCall : 1;
125 bool m_replied : 1; 153 bool m_replied : 1;
126 bool m_inEventHandler : 1; 154 bool m_inEventHandler : 1;
127 Mutex m_guard; 155 Mutex m_guard;
128 WaitCondition m_condition; 156 WaitCondition m_condition;
129 QGuardedPtr<Channel> m_channel; 157 QGuardedPtr<Channel> m_channel;
130 }; 158 };
131 159
132 class Channel : public QObject 160 class Channel : public QObject
133 { 161 {
134 Q_OBJECT 162 Q_OBJECT
135 public: 163 public:
136 enum SendType { OneWay, WaitForReply }; 164 enum SendType { OneWay, WaitForReply };
137 Channel( QObject *parent = 0, const char *name = 0 ); 165 Channel( QObject *parent = 0, const char *name = 0 );
138 virtual ~Channel(); 166 virtual ~Channel();
139 167
140 void send( ChannelMessage *message, SendType type ); 168 void send( ChannelMessage *message, SendType type );
141 169
142 protected: 170 protected:
143 virtual void receiveMessage( ChannelMessage *message, SendType type ) = 0; 171 virtual void receiveMessage( ChannelMessage *message, SendType type ) = 0;
144 172
145 private slots: 173 private slots:
146 void deliver(); 174 void deliver();
147 175
148 private: 176 private:
149 OnewayNotifier m_notifier; 177 OnewayNotifier m_notifier;
150 178
151 struct MsgEnvelope 179 struct MsgEnvelope
152 { 180 {
153 MsgEnvelope() : type( OneWay ), msg( 0 ) {} 181 MsgEnvelope() : type( OneWay ), msg( 0 ) {}
154 MsgEnvelope( SendType _type , ChannelMessage *_msg ) 182 MsgEnvelope( SendType _type , ChannelMessage *_msg )
155 : type( _type ), msg( _msg ) {} 183 : type( _type ), msg( _msg ) {}
156 184
157 SendType type; 185 SendType type;
158 ChannelMessage *msg; 186 ChannelMessage *msg;
159 }; 187 };
160 188
161 void deliverOne( const MsgEnvelope &envelope ); 189 void deliverOne( const MsgEnvelope &envelope );
162 190
163 typedef QValueList<MsgEnvelope> MsgEnvelopeList; 191 typedef QValueList<MsgEnvelope> MsgEnvelopeList;
164 192
165 MsgEnvelopeList m_pendingMessages; 193 MsgEnvelopeList m_pendingMessages;
166 Mutex m_pendingMessagesGuard; 194 Mutex m_pendingMessagesGuard;
167 195
168 struct Private; 196 struct Private;
169 Private *d; 197 Private *d;
170 }; 198 };
171 199
172} 200}
173 201
174#endif // THREADUTIL_H 202#endif // THREADUTIL_H
175/* vim: et sw=4 ts=4 203/* vim: et sw=4 ts=4
176 */ 204 */