00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef FXBEING_INCLUDED_BY_QTHREAD
00023 #error This file is not supposed to be included by public code
00024 #endif
00025
00026
00027
00028 #include "FXErrCodes.h"
00029 #include "FXRollback.h"
00030
00031 #ifdef FXDISABLE_THREADS
00032 #undef USE_WINAPI
00033 #undef USE_OURMUTEX
00034 #undef USE_X86
00035 #else
00036
00037 #ifndef USE_POSIX
00038 #define USE_WINAPI
00039 #define USE_OURMUTEX
00040 #include "WindowsGubbins.h"
00041 #include <intrin.h>
00042 #endif
00043 #ifdef USE_POSIX
00044
00045 #define __CLEANUP_C // for pthreads_win32
00046
00047 #include <semaphore.h>
00048 #include <pthread.h>
00049 #endif
00050 #endif
00051
00052 #include <assert.h>
00053
00054
00055 #ifdef USE_WINAPI
00056 #define USE_OURMUTEX
00057 #ifdef _MSC_VER
00058
00059 #pragma intrinsic (_InterlockedCompareExchange)
00060 #pragma intrinsic (_InterlockedExchange)
00061 #pragma intrinsic (_InterlockedExchangeAdd)
00062 #pragma intrinsic (_InterlockedIncrement)
00063 #pragma intrinsic (_InterlockedDecrement)
00064 #endif
00065 #else
00066
00067 #if defined(__GNUC__)
00068 #define USE_OURMUTEX
00069 #if (defined(__i386__) || defined(__x86_64__))
00070 #define USE_X86 FX_X86PROCESSOR // On x86 or x64, use inline assembler
00071 #else
00072 #include <bits/atomicity.h>
00073 #endif
00074 #endif
00075 #endif
00076
00077 #ifndef USE_OURMUTEX
00078 #error Unsupported compiler, please add atomic int support to QThread.cxx
00079 #endif
00080
00081 namespace FX {
00082
00083 QMUTEX_INLINEI int FXAtomicInt::get() const throw()
00084 {
00085 return value;
00086 }
00087 QMUTEX_INLINEP FXAtomicInt::operator int() const throw() { return get(); }
00088 QMUTEX_INLINEI int FXAtomicInt::set(int i) throw()
00089 {
00090 #ifdef __GNUC__
00091 int d;
00092 #ifdef USE_X86
00093 __asm__ __volatile__ ("xchgl %2,(%1)" : "=r" (d) : "r" (&value), "0" (i));
00094 #else
00095 while(__gnu_cxx::__exchange_and_add((_Atomic_word *) &lock, 1)) __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00096 value=i;
00097 __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00098 #endif
00099 #elif defined(USE_WINAPI)
00100 _InterlockedExchange((PLONG) &value, i);
00101 #endif
00102 return i;
00103 }
00104 QMUTEX_INLINEP int FXAtomicInt::operator=(int i) throw() { return set(i); }
00105 QMUTEX_INLINEI int FXAtomicInt::incp() throw()
00106 {
00107 #ifdef __GNUC__
00108 int myret;
00109 #ifdef USE_X86
00110 __asm__ __volatile__ (
00111 #ifdef FX_SMPBUILD
00112 "lock/xaddl %2,(%1)"
00113 #else
00114 "xaddl %2,(%1)"
00115 #endif
00116 : "=a" (myret) : "r" (&value), "a" (1));
00117 #else
00118 while(__gnu_cxx::__exchange_and_add((_Atomic_word *) &lock, 1)) __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00119 myret=value++;
00120 __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00121 #endif
00122 return myret;
00123 #elif defined(USE_WINAPI)
00124 return _InterlockedExchangeAdd((PLONG) &value, 1);
00125 #endif
00126 }
00127 QMUTEX_INLINEP int FXAtomicInt::operator++(int) throw() { return incp(); }
00128 QMUTEX_INLINEI int FXAtomicInt::pinc() throw()
00129 {
00130 #ifdef __GNUC__
00131 int myret;
00132 #ifdef USE_X86
00133 __asm__ __volatile__ (
00134 #ifdef FX_SMPBUILD
00135 "lock/xaddl %2,(%1)\n\tinc %%eax"
00136 #else
00137 "xaddl %2,(%1)\n\tinc %%eax"
00138 #endif
00139 : "=a" (myret) : "r" (&value), "a" (1));
00140 #else
00141 while(__gnu_cxx::__exchange_and_add((_Atomic_word *) &lock, 1)) __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00142 myret=++value;
00143 __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00144 #endif
00145 return myret;
00146 #elif defined(USE_WINAPI)
00147 return _InterlockedIncrement((PLONG) &value);
00148 #endif
00149 }
00150 QMUTEX_INLINEP int FXAtomicInt::operator++() throw() { return pinc(); }
00151 QMUTEX_INLINEI int FXAtomicInt::finc() throw()
00152 {
00153 #ifdef __GNUC__
00154 int myret;
00155 #if defined(USE_X86)
00156 __asm__ __volatile__ (
00157 #ifdef FX_SMPBUILD
00158 "lock/incl (%1)\n"
00159 #else
00160 "incl (%1)\n"
00161 #endif
00162 "\tjl 1f\n\tjg 2f\n"
00163 "\tmov $0, %%eax\n\tjmp 3f\n"
00164 "1:\tmov $-1, %%eax\n\tjmp 3f\n"
00165 "2:\tmov $1, %%eax\n"
00166 "3:\n"
00167 : "=a" (myret) : "r" (&value));
00168 #else
00169 return pinc();
00170 #endif
00171 return myret;
00172 #else
00173 return pinc();
00174 #endif
00175 }
00176 QMUTEX_INLINEP int FXAtomicInt::fastinc() throw() { return finc(); }
00177 QMUTEX_INLINEI int FXAtomicInt::inc(int i) throw()
00178 {
00179 #ifdef __GNUC__
00180 int myret;
00181 #ifdef USE_X86
00182 __asm__ __volatile__ (
00183 #ifdef FX_SMPBUILD
00184 "lock/xaddl %2,(%1)"
00185 #else
00186 "xaddl %2,(%1)"
00187 #endif
00188 : "=a" (myret) : "r" (&value), "a" (i));
00189 #else
00190 while(__gnu_cxx::__exchange_and_add((_Atomic_word *) &lock, 1)) __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00191 myret=(value+=i);
00192 __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00193 #endif
00194 return myret+i;
00195 #elif defined(USE_WINAPI)
00196 return _InterlockedExchangeAdd((PLONG) &value, i)+i;
00197 #endif
00198 }
00199 QMUTEX_INLINEP int FXAtomicInt::operator+=(int i) throw() { return inc(i); }
00200 QMUTEX_INLINEI int FXAtomicInt::decp() throw()
00201 {
00202 #ifdef __GNUC__
00203 int myret;
00204 #ifdef USE_X86
00205 __asm__ __volatile__ (
00206 #ifdef FX_SMPBUILD
00207 "lock/xaddl %2,(%1)"
00208 #else
00209 "xaddl %2,(%1)"
00210 #endif
00211 : "=a" (myret) : "r" (&value), "a" (-1));
00212 #else
00213 while(__gnu_cxx::__exchange_and_add((_Atomic_word *) &lock, 1)) __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00214 myret=value--;
00215 __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00216 #endif
00217 return myret;
00218 #elif defined(USE_WINAPI)
00219 return _InterlockedExchangeAdd((PLONG) &value, -1);
00220 #endif
00221 }
00222 QMUTEX_INLINEP int FXAtomicInt::operator--(int) throw() { return decp(); }
00223 QMUTEX_INLINEI int FXAtomicInt::pdec() throw()
00224 {
00225 #ifdef __GNUC__
00226 int myret;
00227 #ifdef USE_X86
00228 __asm__ __volatile__ (
00229 #ifdef FX_SMPBUILD
00230 "lock/xaddl %2,(%1)\n\tdec %%eax"
00231 #else
00232 "xaddl %2,(%1)\n\tdec %%eax"
00233 #endif
00234 : "=a" (myret) : "r" (&value), "a" (-1));
00235 #else
00236 while(__gnu_cxx::__exchange_and_add((_Atomic_word *) &lock, 1)) __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00237 myret=--value;
00238 __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00239 #endif
00240 return myret;
00241 #elif defined(USE_WINAPI)
00242 return _InterlockedDecrement((PLONG) &value);
00243 #endif
00244 }
00245 QMUTEX_INLINEP int FXAtomicInt::operator--() throw() { return pdec(); }
00246 QMUTEX_INLINEI int FXAtomicInt::fdec() throw()
00247 {
00248 #ifdef __GNUC__
00249 int myret;
00250 #if defined(USE_X86)
00251 __asm__ __volatile__ (
00252 #ifdef FX_SMPBUILD
00253 "lock/decl (%1)\n"
00254 #else
00255 "decl (%1)\n"
00256 #endif
00257 "\tjl 1f\n\tjg 2f\n"
00258 "\tmov $0, %%eax\n\tjmp 3f\n"
00259 "1:\tmov $-1, %%eax\n\tjmp 3f\n"
00260 "2:\tmov $1, %%eax\n"
00261 "3:\n"
00262 : "=a" (myret) : "r" (&value));
00263 #else
00264 return pdec();
00265 #endif
00266 return myret;
00267 #else
00268 return pdec();
00269 #endif
00270 }
00271 QMUTEX_INLINEP int FXAtomicInt::fastdec() throw() { return fdec(); }
00272 QMUTEX_INLINEI int FXAtomicInt::dec(int i) throw()
00273 {
00274 #ifdef __GNUC__
00275 int myret;
00276 i=-i;
00277 #ifdef USE_X86
00278 __asm__ __volatile__ (
00279 #ifdef FX_SMPBUILD
00280 "lock/xaddl %2,(%1)"
00281 #else
00282 "xaddl %2,(%1)"
00283 #endif
00284 : "=a" (myret) : "r" (&value), "a" (i));
00285 #else
00286 while(__gnu_cxx::__exchange_and_add((_Atomic_word *) &lock, 1)) __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00287 myret=(value-=i);
00288 __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00289 #endif
00290 return myret+i;
00291 #elif defined(USE_WINAPI)
00292 return _InterlockedExchangeAdd((PLONG) &value, -i)-i;
00293 #endif
00294 }
00295 QMUTEX_INLINEP int FXAtomicInt::operator-=(int i) throw() { return dec(i); }
00296 QMUTEX_INLINEI int FXAtomicInt::swapI(int i) throw()
00297 {
00298 #ifdef __GNUC__
00299 int myret;
00300 #ifdef USE_X86
00301 __asm__ __volatile__ ("xchgl %2,(%1)" : "=r" (myret) : "r" (&value), "0" (i));
00302 #else
00303 while(__gnu_cxx::__exchange_and_add((_Atomic_word *) &lock, 1)) __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00304 myret=value;
00305 value=i;
00306 __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00307 #endif
00308 return myret;
00309 #elif defined(USE_WINAPI)
00310 return _InterlockedExchange((PLONG) &value, i);
00311 #endif
00312 }
00313 QMUTEX_INLINEP int FXAtomicInt::swap(int i) throw() { return swapI(i); }
00314 QMUTEX_INLINEI int FXAtomicInt::cmpXI(int compare, int newval) throw()
00315 {
00316 #ifdef __GNUC__
00317 int myret;
00318 #ifdef USE_X86
00319 __asm__ __volatile__ (
00320 #ifdef FX_SMPBUILD
00321 "pause\n\tlock/cmpxchgl %2,(%1)"
00322 #else
00323 "pause\n\tcmpxchgl %2,(%1)"
00324 #endif
00325 : "=a" (myret) : "r" (&value), "r" (newval), "a" (compare));
00326 #else
00327 while(__gnu_cxx::__exchange_and_add((_Atomic_word *) &lock, 1)) __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00328 myret=value;
00329 if(value==compare)
00330 value=newval;
00331 __gnu_cxx::__atomic_add((_Atomic_word *) &lock, -1);
00332 #endif
00333 return myret;
00334 #elif defined(USE_WINAPI)
00335 return _InterlockedCompareExchange((PLONG) &value, newval, compare);
00336 #endif
00337 }
00338 QMUTEX_INLINEP int FXAtomicInt::cmpX(int compare, int newval) throw() { return cmpXI(compare, newval); }
00339 #if 0
00340
00341
00342
00343 QMUTEX_INLINEI int FXAtomicInt::spinI(int count) throw()
00344 {
00345 int myret;
00346 #ifdef USE_X86
00347 #ifdef __GNUC__
00348 #error todo
00349 __asm__ __volatile__ (
00350 #ifdef FX_SMPBUILD
00351 "pause\n\tlock/cmpxchgl %2,(%1)"
00352 #else
00353 "pause\n\tcmpxchgl %2,(%1)"
00354 #endif
00355 : "=a" (myret) : "r" (&value), "r" (newval), "a" (compare));
00356 #endif
00357 return myret;
00358 #elif defined(USE_WINAPI)
00359 for(int n=0; n<count && (myret=_InterlockedExchange((PLONG) &value, 1)); n++)
00360 return myret;
00361 #endif
00362 }
00363 #endif
00364
00365
00366
00367 QMUTEX_INLINEP void QShrdMemMutex::lock()
00368 {
00369 FXuint start=!timeout ? 0 : FXProcess::getMsCount();
00370 while(lockvar.swapI(1) && (!timeout || FXProcess::getMsCount()-start<timeout-1))
00371 #ifndef FX_SMPBUILD
00372 QThread::yield()
00373 #endif
00374 ;
00375 }
00376
00377 QMUTEX_INLINEP bool QShrdMemMutex::tryLock() throw()
00378 {
00379 return !lockvar.swapI(1);
00380 }
00381
00382
00383
00384 #ifndef FXDISABLE_THREADS
00385 namespace QMutexImpl {
00386
00387
00388
00389
00390
00391
00392
00393
00394 #if !defined(__FreeBSD__) && !defined(__APPLE__)
00395 #define MUTEX_USESEMA
00396 #endif
00397
00398
00399
00400
00401 class FXDLLLOCAL KernelWaitObjectCache
00402 {
00403 QShrdMemMutex lockvar;
00404 public:
00405 #ifdef USE_WINAPI
00406 typedef HANDLE WaitObjectType;
00407 #endif
00408 #ifdef USE_POSIX
00409 #ifdef MUTEX_USESEMA
00410 typedef sem_t WaitObjectType;
00411 #else
00412 typedef pthread_mutex_t WaitObjectType;
00413 #endif
00414 #endif
00415 struct Entry
00416 {
00417 WaitObjectType wo;
00418 Entry *next;
00419 };
00420 private:
00421 Entry *entries;
00422 QMUTEX_INLINEI void lock() throw() { lockvar.lock(); }
00423 QMUTEX_INLINEI void unlock() throw() { lockvar.unlock(); }
00424 public:
00425 bool dead;
00426 KernelWaitObjectCache() : lockvar(FXINFINITE) { }
00427 ~KernelWaitObjectCache()
00428 {
00429 lock();
00430 FXRBOp undolock=FXRBObj(*this, &KernelWaitObjectCache::unlock);
00431 while(entries)
00432 {
00433 #ifdef USE_WINAPI
00434 FXERRHWIN(CloseHandle(entries->wo));
00435 #endif
00436 #ifdef USE_POSIX
00437 #ifdef MUTEX_USESEMA
00438 FXERRHOS(sem_destroy(&entries->wo));
00439 #else
00440 FXERRHOS(pthread_mutex_destroy(&entries->wo));
00441 #endif
00442 #endif
00443 Entry *e=entries;
00444 entries=e->next;
00445 FXDELETE(e);
00446 }
00447 dead=true;
00448 }
00449 Entry *fetch() throw()
00450 {
00451 if(!entries) return 0;
00452 lock();
00453 if(!entries)
00454 {
00455 unlock();
00456 return 0;
00457 }
00458 Entry *ret=entries;
00459 entries=entries->next;
00460 unlock();
00461 return ret;
00462 }
00463 void addFreed(Entry *e) throw()
00464 {
00465 if(dead)
00466 delete e;
00467 else
00468 {
00469 lock();
00470 e->next=entries;
00471 entries=e;
00472 unlock();
00473 }
00474 }
00475 };
00476 extern QMUTEX_GLOBALS_FXAPI KernelWaitObjectCache waitObjectCache;
00477 extern QMUTEX_GLOBALS_FXAPI bool yieldAfterLock;
00478 extern QMUTEX_GLOBALS_FXAPI FXuint systemProcessors;
00479
00480 }
00481 #endif
00482
00483 struct FXDLLLOCAL QMutexPrivate
00484 {
00485 #ifndef FXDISABLE_THREADS
00486 #ifdef USE_OURMUTEX
00487 FXAtomicInt lockCount, wakeSema;
00488 FXulong threadId;
00489 FXuint recurseCount, spinCount;
00490 #ifdef USE_WINAPI
00491 QMutexImpl::KernelWaitObjectCache::Entry *wc;
00492 #endif
00493 #ifdef USE_POSIX
00494 QMutexImpl::KernelWaitObjectCache::Entry *sema;
00495 #endif
00496 #elif defined(USE_POSIX)
00497 QMutexImpl::KernelWaitObjectCache::Entry *m;
00498 #endif
00499 #endif
00500 };
00501
00502 QMUTEX_INLINEP QMutex::QMutex(FXuint spinc) : p(0)
00503 {
00504 FXRBOp unconstr=FXRBConstruct(this);
00505 FXERRHM(p=new QMutexPrivate);
00506 #ifndef FXDISABLE_THREADS
00507 #ifdef USE_OURMUTEX
00508 p->lockCount.set(-1);
00509 p->wakeSema.set(0);
00510 p->threadId=p->recurseCount=0;
00511 if(!QMutexImpl::systemProcessors)
00512 QMutexImpl::systemProcessors=FXProcess::noOfProcessors();
00513 p->spinCount=spinc;
00514 #ifdef USE_WINAPI
00515 if(!(p->wc=QMutexImpl::waitObjectCache.fetch()))
00516 {
00517 FXERRHM(p->wc=new QMutexImpl::KernelWaitObjectCache::Entry);
00518 FXRBOp unwc=FXRBNew(p->wc);
00519 FXERRHWIN(p->wc->wo=CreateEvent(NULL, FALSE, FALSE, NULL));
00520 unwc.dismiss();
00521 }
00522 #endif
00523 #ifdef USE_POSIX
00524 #ifdef MUTEX_USESEMA
00525 if(!(p->sema=QMutexImpl::waitObjectCache.fetch()))
00526 {
00527 FXERRHM(p->sema=new QMutexImpl::KernelWaitObjectCache::Entry);
00528 FXRBOp unsema=FXRBNew(p->sema);
00529 FXERRHOS(sem_init(&p->sema->wo, 0, 0));
00530 unsema.dismiss();
00531 }
00532 #else
00533 if(!(p->sema=QMutexImpl::waitObjectCache.fetch()))
00534 {
00535 FXERRHM(p->sema=new QMutexImpl::KernelWaitObjectCache::Entry);
00536 FXRBOp unsema=FXRBNew(p->sema);
00537 FXERRHOS(pthread_mutex_init(&p->sema->wo, NULL));
00538 unsema.dismiss();
00539 }
00540 #endif
00541 #endif
00542 #elif defined(USE_POSIX)
00543 pthread_mutexattr_t mattr;
00544 FXERRHOS(pthread_mutexattr_init(&mattr));
00545 FXERRHOS(pthread_mutexattr_setkind_np(&mattr, PTHREAD_MUTEX_RECURSIVE_NP));
00546 if(!(p->m=waitObjectCache.fetch()))
00547 {
00548 FXERRHM(p->m=new KernelWaitObjectCache::Entry);
00549 FXRBOp unm=FXRBNew(p->m);
00550 FXERRHOS(pthread_mutex_init(&p->m->wo, &mattr));
00551 unm.dismiss();
00552 }
00553 FXERRHOS(pthread_mutexattr_destroy(&mattr));
00554 #endif
00555 #endif
00556 unconstr.dismiss();
00557 }
00558
00559 QMUTEX_INLINEP QMutex::~QMutex()
00560 { FXEXCEPTIONDESTRUCT1 {
00561 if(p)
00562 {
00563 QMutexPrivate *_p=p;
00564 p=0;
00565 #ifndef FXDISABLE_THREADS
00566 #ifdef USE_OURMUTEX
00567 #ifdef USE_WINAPI
00568 if(_p->wc && _p->wc->wo)
00569 {
00570 FXERRHWIN(ResetEvent(_p->wc->wo));
00571 QMutexImpl::waitObjectCache.addFreed(_p->wc);
00572 _p->wc=0;
00573 }
00574 #endif
00575 #ifdef USE_POSIX
00576 if(_p->sema)
00577 {
00578 QMutexImpl::waitObjectCache.addFreed(_p->sema);
00579 _p->sema=0;
00580 }
00581 #endif
00582 #elif defined(USE_POSIX)
00583 if(_p->m)
00584 {
00585 QMutexImpl::waitObjectCache.addFreed(_p->m);
00586 p->m=0;
00587 }
00588 #endif
00589 #endif
00590 FXDELETE(_p);
00591 }
00592 } FXEXCEPTIONDESTRUCT2; }
00593
00594 QMUTEX_INLINEP bool QMutex::isLocked() const
00595 {
00596 #ifndef FXDISABLE_THREADS
00597 return p->lockCount>=0;
00598 #else
00599 return false;
00600 #endif
00601 }
00602
00603 QMUTEX_INLINEP FXuint QMutex::spinCount() const
00604 {
00605 #ifndef FXDISABLE_THREADS
00606 #ifdef USE_OURMUTEX
00607 return p->spinCount;
00608 #else
00609 return 0;
00610 #endif
00611 #else
00612 return 0;
00613 #endif
00614 }
00615
00616 QMUTEX_INLINEP void QMutex::setSpinCount(FXuint c)
00617 {
00618 #ifndef FXDISABLE_THREADS
00619 #ifdef USE_OURMUTEX
00620 p->spinCount=c;
00621 #endif
00622 #endif
00623 }
00624
00625 QMUTEX_INLINEI void QMutex::int_lock()
00626 {
00627 assert(this);
00628 assert(p);
00629 if(!p) return;
00630 #ifndef FXDISABLE_THREADS
00631 #ifdef USE_OURMUTEX
00632 FXulong myid=QThread::id();
00633 if(!p->lockCount.finc())
00634 {
00635 assert(p->threadId==0);
00636 assert(p->recurseCount==0);
00637 p->threadId=myid;
00638 p->recurseCount=1;
00639 }
00640 else
00641 {
00642 if(p->threadId==myid)
00643 {
00644 p->recurseCount++;
00645 }
00646 else
00647 {
00648 #if 0
00649
00650
00651 int gotit;
00652 while(!(gotit=p->wakeSema.swapI(0)))
00653 {
00654 gotit=p->wakeSema.spinI(p->spinCount*3);
00655 #else
00656 int gotit;
00657 while(!(gotit=p->wakeSema.swapI(0)))
00658 {
00659 for(FXuint n=0; n<p->spinCount; n++)
00660 {
00661 if(1==QMutexImpl::systemProcessors)
00662 {
00663 #ifdef USE_WINAPI
00664 Sleep(0);
00665 #endif
00666 #ifdef USE_POSIX
00667 sched_yield();
00668 #endif
00669 }
00670 if((gotit=p->wakeSema.swapI(0)))
00671 {
00672 break;
00673 }
00674 }
00675 #endif
00676 if(gotit)
00677 break;
00678 else
00679 {
00680 #ifdef USE_WINAPI
00681 WaitForSingleObject(p->wc->wo, INFINITE);
00682 #endif
00683 #if defined(USE_POSIX) && defined(MUTEX_USESEMA)
00684 QThread *c=QThread::current();
00685 if(c) c->disableTermination();
00686 sem_wait(&p->sema->wo);
00687 if(c) c->enableTermination();
00688 #endif
00689 }
00690 }
00691 #if defined(USE_POSIX) && !defined(MUTEX_USESEMA)
00692 pthread_mutex_lock(&p->sema->wo);
00693 #endif
00694
00695 {
00696 assert(p->threadId==0);
00697 p->threadId=myid;
00698 assert(p->recurseCount==0);
00699 p->recurseCount=1;
00700 }
00701 }
00702 }
00703 #elif defined(USE_POSIX)
00704 FXERRHOS(pthread_mutex_lock(&p->m->wo));
00705 #endif
00706 if(QMutexImpl::yieldAfterLock) QThread::yield();
00707 #endif
00708 }
00709 QMUTEX_INLINEP void QMutex::lock() { int_lock(); }
00710
00711 QMUTEX_INLINEI void QMutex::int_unlock()
00712 {
00713 assert(this);
00714 assert(p);
00715 if(!p) return;
00716 #ifndef FXDISABLE_THREADS
00717 #ifdef USE_OURMUTEX
00718 if(--p->recurseCount>0)
00719 {
00720 assert(p->recurseCount<0x80000000);
00721 p->lockCount.fdec();
00722 }
00723 else
00724 {
00725 #ifdef DEBUG
00726 FXulong myid=QThread::id();
00727 if(myid && p->threadId)
00728 FXERRH(QThread::id()==p->threadId, "QMutex::unlock() performed by thread which did not own mutex", QMUTEX_BADUNLOCK, FXERRH_ISDEBUG);
00729 #endif
00730 p->threadId=0;
00731
00732 if(p->lockCount.fdec()>=0)
00733 {
00734 p->wakeSema.set(1);
00735 #ifdef USE_WINAPI
00736 SetEvent(p->wc->wo);
00737 #endif
00738 #if defined(USE_POSIX) && defined(MUTEX_USESEMA)
00739 sem_post(&p->sema->wo);
00740 #endif
00741 }
00742 #if defined(USE_POSIX) && !defined(MUTEX_USESEMA)
00743 pthread_mutex_unlock(&p->sema->wo);
00744 #endif
00745 }
00746 #elif defined(USE_POSIX)
00747 FXERRHOS(pthread_mutex_unlock(&p->m->wo));
00748 #endif
00749 #endif
00750 }
00751 QMUTEX_INLINEP void QMutex::unlock() { int_unlock(); }
00752
00753 QMUTEX_INLINEP bool QMutex::tryLock()
00754 {
00755 #ifndef FXDISABLE_THREADS
00756 #ifdef USE_OURMUTEX
00757 FXulong myid=QThread::id();
00758 if(!p->lockCount.finc())
00759 {
00760 assert(p->threadId==0);
00761 p->threadId=myid;
00762 p->recurseCount=1;
00763 return true;
00764 }
00765 else
00766 {
00767 if(p->threadId==myid)
00768 {
00769 p->recurseCount++;
00770 return true;
00771 }
00772
00773 p->lockCount.fdec();
00774 return false;
00775 }
00776 #elif defined(USE_POSIX)
00777
00778 if(0==pthread_mutex_trylock(&p->m->wo))
00779 return true;
00780 else
00781 return false;
00782 #endif
00783 #endif
00784 }
00785
00786 QMUTEX_INLINEP bool QMutex::setMutexDebugYield(bool v)
00787 {
00788 #ifndef FXDISABLE_THREADS
00789 bool old=QMutexImpl::yieldAfterLock;
00790 QMutexImpl::yieldAfterLock=v;
00791 return old;
00792 #endif
00793 }
00794
00795 }