summaryrefslogtreecommitdiff
path: root/noncore/multimedia/opieplayer2/threadutil.cpp
Unidiff
Diffstat (limited to 'noncore/multimedia/opieplayer2/threadutil.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/multimedia/opieplayer2/threadutil.cpp17
1 files changed, 11 insertions, 6 deletions
diff --git a/noncore/multimedia/opieplayer2/threadutil.cpp b/noncore/multimedia/opieplayer2/threadutil.cpp
index b5cac61..5fc8a0b 100644
--- a/noncore/multimedia/opieplayer2/threadutil.cpp
+++ b/noncore/multimedia/opieplayer2/threadutil.cpp
@@ -44,351 +44,356 @@ struct Mutex::Data
44}; 44};
45 45
46Mutex::Mutex() 46Mutex::Mutex()
47 : d( new Data ) 47 : d( new Data )
48{ 48{
49} 49}
50 50
51Mutex::~Mutex() 51Mutex::~Mutex()
52{ 52{
53 delete d; 53 delete d;
54} 54}
55 55
56void Mutex::lock() 56void Mutex::lock()
57{ 57{
58 pthread_mutex_lock( &d->mutex ); 58 pthread_mutex_lock( &d->mutex );
59} 59}
60 60
61void Mutex::unlock() 61void Mutex::unlock()
62{ 62{
63 pthread_mutex_unlock( &d->mutex ); 63 pthread_mutex_unlock( &d->mutex );
64} 64}
65 65
66bool Mutex::tryLock() 66bool Mutex::tryLock()
67{ 67{
68 return pthread_mutex_trylock( &d->mutex ) == 0; 68 return pthread_mutex_trylock( &d->mutex ) == 0;
69} 69}
70 70
71bool Mutex::isLocked() 71bool Mutex::isLocked()
72{ 72{
73 if ( !tryLock() ) 73 if ( !tryLock() )
74 return true; 74 return true;
75 75
76 unlock(); 76 unlock();
77 return false; 77 return false;
78} 78}
79 79
80struct WaitCondition::Data 80struct WaitCondition::Data
81{ 81{
82 Data() 82 Data()
83 { 83 {
84 int result = pthread_cond_init( &waitCondition, 0 ); 84 int result = pthread_cond_init( &waitCondition, 0 );
85 assert( result == 0 ); 85 assert( result == 0 );
86 } 86 }
87 ~Data() 87 ~Data()
88 { 88 {
89 pthread_cond_destroy( &waitCondition ); 89 pthread_cond_destroy( &waitCondition );
90 } 90 }
91 91
92 pthread_cond_t waitCondition; 92 pthread_cond_t waitCondition;
93}; 93};
94 94
95WaitCondition::WaitCondition() 95WaitCondition::WaitCondition()
96 : d( new Data ) 96 : d( new Data )
97{ 97{
98} 98}
99 99
100WaitCondition::~WaitCondition() 100WaitCondition::~WaitCondition()
101{ 101{
102 delete d; 102 delete d;
103} 103}
104 104
105bool WaitCondition::wait() 105bool WaitCondition::wait()
106{ 106{
107 Mutex m; 107 Mutex m;
108 m.lock(); 108 m.lock();
109 return wait( m ); 109 return wait( m );
110} 110}
111 111
112bool WaitCondition::wait( Mutex &mutex ) 112bool WaitCondition::wait( Mutex &mutex )
113{ 113{
114 return pthread_cond_wait( &d->waitCondition, &mutex.d->mutex ); 114 return pthread_cond_wait( &d->waitCondition, &mutex.d->mutex );
115} 115}
116 116
117void WaitCondition::wakeOne() 117void WaitCondition::wakeOne()
118{ 118{
119 pthread_cond_signal( &d->waitCondition ); 119 pthread_cond_signal( &d->waitCondition );
120} 120}
121 121
122void WaitCondition::wakeAll() 122void WaitCondition::wakeAll()
123{ 123{
124 pthread_cond_broadcast( &d->waitCondition ); 124 pthread_cond_broadcast( &d->waitCondition );
125} 125}
126 126
127struct Thread::Data 127struct Thread::Data
128{ 128{
129 Data() : isRunning( false ) 129 Data() : isRunning( false )
130 {} 130 {}
131 131
132 pthread_t self; 132 pthread_t self;
133 Mutex guard; 133 Mutex guard;
134 bool isRunning; 134 bool isRunning;
135 135
136 WaitCondition finishCondition; 136 WaitCondition finishCondition;
137 137
138 Thread *thr; 138 Thread *thr;
139 139
140 void run() { thr->run(); } 140 void run() { thr->run(); }
141}; 141};
142 142
143extern "C" 143extern "C"
144{ 144{
145 145
146static void terminate_thread( void *arg ) 146static void terminate_thread( void *arg )
147{ 147{
148 Thread::Data *data = ( Thread::Data* )arg; 148 Thread::Data *data = ( Thread::Data* )arg;
149 149
150 assert( data ); 150 assert( data );
151 151
152 AutoLock locker( data->guard ); 152 AutoLock locker( data->guard );
153 data->isRunning = false; 153 data->isRunning = false;
154 data->finishCondition.wakeAll(); 154 data->finishCondition.wakeAll();
155} 155}
156 156
157static void *start_thread( void *arg ) 157static void *start_thread( void *arg )
158{ 158{
159 Thread::Data *data = ( Thread::Data* )arg; 159 Thread::Data *data = ( Thread::Data* )arg;
160 160
161 pthread_cleanup_push( terminate_thread, data ); 161 pthread_cleanup_push( terminate_thread, data );
162 162
163 data->isRunning = true; 163 data->isRunning = true;
164 data->run(); 164 data->run();
165 165
166 pthread_cleanup_pop( true ); 166 pthread_cleanup_pop( true );
167 167
168 Thread::exit(); 168 Thread::exit();
169 return 0; // never reached 169 return 0; // never reached
170} 170}
171 171
172} 172}
173 173
174Thread::Thread() 174Thread::Thread()
175 : d( new Data ) 175 : d( new Data )
176{ 176{
177 d->thr = this; 177 d->thr = this;
178} 178}
179 179
180Thread::~Thread() 180Thread::~Thread()
181{ 181{
182 assert( d->isRunning == false ); 182 assert( d->isRunning == false );
183 delete d; 183 delete d;
184} 184}
185 185
186void Thread::start() 186void Thread::start()
187{ 187{
188 AutoLock lock( d->guard ); 188 AutoLock lock( d->guard );
189 189
190 if ( d->isRunning ) { 190 if ( d->isRunning ) {
191 odebug << "ThreadUtil::Thread::start() called for running thread." << oendl; 191 odebug << "ThreadUtil::Thread::start() called for running thread." << oendl;
192 return; 192 return;
193 } 193 }
194 194
195 pthread_attr_t attributes; 195 pthread_attr_t attributes;
196 pthread_attr_init( &attributes ); 196 pthread_attr_init( &attributes );
197 pthread_attr_setscope( &attributes, PTHREAD_SCOPE_SYSTEM ); 197 pthread_attr_setscope( &attributes, PTHREAD_SCOPE_SYSTEM );
198 int err = pthread_create( &d->self, &attributes, start_thread, ( void* )d ); 198 int err = pthread_create( &d->self, &attributes, start_thread, ( void* )d );
199 if ( err != 0 ) { 199 if ( err != 0 ) {
200 odebug << "ThreadUtil::Thread::start() : can't create thread: " << strerror( err ) << "" << oendl; 200 odebug << "ThreadUtil::Thread::start() : can't create thread: " << strerror( err ) << "" << oendl;
201 pthread_attr_destroy( &attributes ); 201 pthread_attr_destroy( &attributes );
202 return; 202 return;
203 } 203 }
204 pthread_attr_destroy( &attributes ); 204 pthread_attr_destroy( &attributes );
205} 205}
206 206
207void Thread::terminate() 207void Thread::terminate()
208{ 208{
209 AutoLock lock( d->guard ); 209 AutoLock lock( d->guard );
210 if ( !d->isRunning ) 210 if ( !d->isRunning )
211 return; 211 return;
212 212
213 pthread_cancel( d->self ); 213 pthread_cancel( d->self );
214} 214}
215 215
216bool Thread::wait() 216bool Thread::wait()
217{ 217{
218 AutoLock lock( d->guard ); 218 AutoLock lock( d->guard );
219 if ( !d->isRunning ) 219 if ( !d->isRunning )
220 return true; 220 return true;
221 221
222 return d->finishCondition.wait( d->guard ); 222 return d->finishCondition.wait( d->guard );
223} 223}
224 224
225bool Thread::isRunning() const 225bool Thread::isRunning() const
226{ 226{
227 AutoLock lock( d->guard ); 227 AutoLock lock( d->guard );
228 return d->isRunning; 228 return d->isRunning;
229} 229}
230 230
231void Thread::exit() 231void Thread::exit()
232{ 232{
233 pthread_exit( 0 ); 233 pthread_exit( 0 );
234} 234}
235 235
236OnewayNotifier::OnewayNotifier() 236OnewayNotifier::OnewayNotifier() :
237{ 237 m_readFd(-1),
238 int fds[ 2 ]; 238 m_writeFd(-1)
239 pipe( fds ); 239{
240 m_readFd = fds[ 0 ]; 240 int fds[ 2 ] = { -1, -1 };
241 m_writeFd = fds[ 1 ]; 241 if (pipe( fds ) == 0) {
242 m_readFd = fds[ 0 ];
243 m_writeFd = fds[ 1 ];
244 } else {
245 owarn << "Call to pipe() failed" << oendl;
246 }
242 247
243 m_notifier = new QSocketNotifier( m_readFd, QSocketNotifier::Read ); 248 m_notifier = new QSocketNotifier( m_readFd, QSocketNotifier::Read );
244 connect( m_notifier, SIGNAL( activated(int) ), 249 connect( m_notifier, SIGNAL( activated(int) ),
245 this, SLOT( wakeUp() ) ); 250 this, SLOT( wakeUp() ) );
246} 251}
247 252
248OnewayNotifier::~OnewayNotifier() 253OnewayNotifier::~OnewayNotifier()
249{ 254{
250 delete m_notifier; 255 delete m_notifier;
251 256
252 ::close( m_readFd ); 257 ::close( m_readFd );
253 ::close( m_writeFd ); 258 ::close( m_writeFd );
254} 259}
255 260
256void OnewayNotifier::notify() 261void OnewayNotifier::notify()
257{ 262{
258 const char c = 42; 263 const char c = 42;
259 ::write( m_writeFd, &c, 1 ); 264 ::write( m_writeFd, &c, 1 );
260} 265}
261 266
262void OnewayNotifier::wakeUp() 267void OnewayNotifier::wakeUp()
263{ 268{
264 char c = 0; 269 char c = 0;
265 270
266 if ( ::read( m_readFd, &c, 1 ) != 1 ) 271 if ( ::read( m_readFd, &c, 1 ) != 1 )
267 return; 272 return;
268 273
269 emit awake(); 274 emit awake();
270} 275}
271 276
272ChannelMessage::ChannelMessage( int type, int data, const char* msg ) 277ChannelMessage::ChannelMessage( int type, int data, const char* msg )
273 : m_type( type ), m_data( data ), m_msg( msg ), 278 : m_type( type ), m_data( data ), m_msg( msg ),
274 m_isCall( false ), m_replied( false ), m_inEventHandler( false ) 279 m_isCall( false ), m_replied( false ), m_inEventHandler( false )
275{} 280{}
276 281
277ChannelMessage::~ChannelMessage() 282ChannelMessage::~ChannelMessage()
278{ 283{
279 if ( m_guard.isLocked() ) 284 if ( m_guard.isLocked() )
280 m_guard.unlock(); 285 m_guard.unlock();
281} 286}
282 287
283void ChannelMessage::reply() 288void ChannelMessage::reply()
284{ 289{
285 if ( !m_isCall ) 290 if ( !m_isCall )
286 { 291 {
287 odebug << "ChannelMessage::reply() - can't reply oneway message!" << oendl; 292 odebug << "ChannelMessage::reply() - can't reply oneway message!" << oendl;
288 return; 293 return;
289 } 294 }
290 295
291 if ( m_inEventHandler ) 296 if ( m_inEventHandler )
292 { 297 {
293 m_replied = true; 298 m_replied = true;
294 return; 299 return;
295 } 300 }
296 301
297 m_condition.wakeOne(); 302 m_condition.wakeOne();
298 m_guard.unlock(); 303 m_guard.unlock();
299} 304}
300 305
301struct Channel::Private 306struct Channel::Private
302{ 307{
303 Private() 308 Private()
304 { 309 {
305 ownerThread = pthread_self(); 310 ownerThread = pthread_self();
306 } 311 }
307 312
308 pthread_t ownerThread; 313 pthread_t ownerThread;
309}; 314};
310 315
311Channel::Channel( QObject *parent, const char *name ) 316Channel::Channel( QObject *parent, const char *name )
312 : QObject( parent, name ), d( new Private ) 317 : QObject( parent, name ), d( new Private )
313{ 318{
314 connect( &m_notifier, SIGNAL( awake() ), 319 connect( &m_notifier, SIGNAL( awake() ),
315 this, SLOT( deliver() ) ); 320 this, SLOT( deliver() ) );
316} 321}
317 322
318Channel::~Channel() 323Channel::~Channel()
319{ 324{
320 delete d; 325 delete d;
321} 326}
322 327
323void Channel::send( ChannelMessage *message, SendType type ) 328void Channel::send( ChannelMessage *message, SendType type )
324{ 329{
325 if ( type == WaitForReply ) 330 if ( type == WaitForReply )
326 { 331 {
327 message->m_guard.lock(); 332 message->m_guard.lock();
328 message->m_isCall = true; 333 message->m_isCall = true;
329 } 334 }
330 335
331 m_pendingMessagesGuard.lock(); 336 m_pendingMessagesGuard.lock();
332 m_pendingMessages << MsgEnvelope( type, message ); 337 m_pendingMessages << MsgEnvelope( type, message );
333 m_pendingMessagesGuard.unlock(); 338 m_pendingMessagesGuard.unlock();
334 339
335 if ( d->ownerThread == pthread_self() ) { 340 if ( d->ownerThread == pthread_self() ) {
336 assert( type != WaitForReply ); 341 assert( type != WaitForReply );
337 342
338 deliver(); 343 deliver();
339 } 344 }
340 else 345 else
341 m_notifier.notify(); 346 m_notifier.notify();
342 //QThread::postEvent( this, new QCustomEvent( QEvent::User, envelope ) ); 347 //QThread::postEvent( this, new QCustomEvent( QEvent::User, envelope ) );
343 348
344 if ( type == WaitForReply ) 349 if ( type == WaitForReply )
345 { 350 {
346 message->m_condition.wait( message->m_guard ); 351 message->m_condition.wait( message->m_guard );
347 message->m_guard.unlock(); 352 message->m_guard.unlock();
348 } 353 }
349} 354}
350 355
351void Channel::deliver() 356void Channel::deliver()
352{ 357{
353 AutoLock lock( m_pendingMessagesGuard ); 358 AutoLock lock( m_pendingMessagesGuard );
354 359
355 while ( !m_pendingMessages.isEmpty() ) { 360 while ( !m_pendingMessages.isEmpty() ) {
356 MsgEnvelope envelope = m_pendingMessages.first(); 361 MsgEnvelope envelope = m_pendingMessages.first();
357 362
358 m_pendingMessages.remove( m_pendingMessages.begin() ); 363 m_pendingMessages.remove( m_pendingMessages.begin() );
359 364
360 m_pendingMessagesGuard.unlock(); 365 m_pendingMessagesGuard.unlock();
361 deliverOne( envelope ); 366 deliverOne( envelope );
362 m_pendingMessagesGuard.lock(); 367 m_pendingMessagesGuard.lock();
363 } 368 }
364} 369}
365 370
366void Channel::deliverOne( const MsgEnvelope &envelope ) 371void Channel::deliverOne( const MsgEnvelope &envelope )
367{ 372{
368 ChannelMessage *msg = envelope.msg; 373 ChannelMessage *msg = envelope.msg;
369 374
370 assert( msg ); 375 assert( msg );
371 376
372 if ( envelope.type == WaitForReply ) 377 if ( envelope.type == WaitForReply )
373 { 378 {
374 msg->m_guard.lock(); 379 msg->m_guard.lock();
375 msg->m_inEventHandler = true; 380 msg->m_inEventHandler = true;
376 } 381 }
377 382
378 receiveMessage( msg, envelope.type ); 383 receiveMessage( msg, envelope.type );
379 384
380 if ( envelope.type == WaitForReply ) 385 if ( envelope.type == WaitForReply )
381 { 386 {
382 msg->m_inEventHandler = false; 387 msg->m_inEventHandler = false;
383 if ( msg->m_replied ) 388 if ( msg->m_replied )
384 { 389 {
385 msg->m_condition.wakeOne(); 390 msg->m_condition.wakeOne();
386 // this is a bit tricky. we unlock only when we reply. 391 // this is a bit tricky. we unlock only when we reply.
387 // reply() does an unlock as well. 392 // reply() does an unlock as well.
388 msg->m_guard.unlock(); 393 msg->m_guard.unlock();
389 } 394 }
390 } 395 }
391} 396}
392 397
393/* vim: et sw=4 ts=4 398/* vim: et sw=4 ts=4
394 */ 399 */