⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tlibmpthrd.cxx

📁 安装 H323需要的pwlib库
💻 CXX
📖 第 1 页 / 共 2 页
字号:
                      0, // no options                      &PX_threadId);  PAssert(err == 0, "MPCreateTask failed");  if (err) throw std::bad_alloc();}long PThread::PX_ThreadStart(void * arg){   MPTaskID threadId = MPCurrentTaskID();  // self-detach (no need)  PThread * thread = (PThread *)arg;  thread->SetThreadName(thread->GetThreadName());  PProcess & process = PProcess::Current();  // add thread to thread list  process.threadMutex.Wait();  process.activeThreads.SetAt((unsigned)threadId, thread);  process.threadMutex.Signal();  // if we are not supposed to start suspended, then don't wait  // if we are supposed to start suspended, then wait for a resume  if (thread->PX_suspendCount != 0) {    thread->suspend_semaphore->Wait();	// Wait for the Resume  }  // now call the the thread main routine  //PTRACE(1, "tlibthrd\tAbout to call Main");  thread->Main();#ifdef DEBUG_THREADS  if (debug_mpthreads)      fprintf(stderr,"thread %p returning\n", thread);#endif  return 0;}void PProcess::SignalTimerChange(){  if (housekeepingThread == NULL) {#if PMEMORY_CHECK    BOOL oldIgnoreAllocations = PMemoryHeap::SetIgnoreAllocations(TRUE);#endif    housekeepingThread = new PHouseKeepingThread;#if PMEMORY_CHECK    PMemoryHeap::SetIgnoreAllocations(oldIgnoreAllocations);#endif  }  SetUpTermQueue();  MPNotifyQueue(terminationNotificationQueue, 0, 0, 0);}void PThread::PX_ThreadEnd(void * arg){  PThread * thread = (PThread *)arg;  PProcess & process = PProcess::Current();    MPTaskID id = thread->PX_GetThreadId();  if (id != 0) {    // remove this thread from the active thread list    process.threadMutex.Wait();    process.activeThreads.SetAt((unsigned)id, NULL);    process.threadMutex.Signal();  }  // delete the thread if required, note this is done this way to avoid  // a race condition, the thread ID cannot be zeroed before the if!  if (thread->autoDelete) {    thread->PX_threadId = 0;  // Prevent terminating terminated thread    delete thread;  }  else    thread->PX_threadId = 0;}MPTaskID PThread::PX_GetThreadId() const{  return PX_threadId;}void PThread::Restart(){  if (IsTerminated())    return;  PX_NewThread(FALSE);}void PThread::Terminate(){  if (PX_origStackSize <= 0)    return;  if (IsTerminated())    return;  PTRACE(1, "tlibthrd\tForcing termination of thread " << (void *)this);  if (Current() == this)      MPExit(0);  else {      MPTaskID taskId = PX_threadId;      WaitForTermination();      // XXX Dire Consequences[TM] are warned of when one uses MPTerminateTask.      // XXX However, the same Dire Consequences are predicted (I think) for      // XXX pthread_kill which the PWLIB code already uses.      // XXX However, the only thing the cleanup function does is removes the      // XXX thread from the thread table, which is already performed by the      // XXX housekeeping thread; PWLIB doesn't try to salvage locks or      // XXX anything clever like that.      // XXX I just hope taskIds aren't quickly reused.      if (taskId != 0)          (void)MPTerminateTask(taskId, kMPTaskAbortedErr);  }}void PThread::PXSetWaitingSemaphore(PSemaphore * sem){    // not needed}BOOL PThread::IsTerminated() const{  if (PX_threadId == 0) {    //PTRACE(1, "tlibthrd\tIsTerminated(" << (void *)this << ") = 0");    return TRUE;  }#ifdef _not_def_ // Sigh.  no MPGetNextTaskID on MOSX  // This seems like a silly way to do this, but I think it might work.  // The end condition for MPGetNextTaskID isn't documented, so I try both  // logical possibilities.  MPTaskID sometask = 0;  MPProcessID myproc = 0;  while (MPGetNextTaskID(myproc, &sometask) == noErr) {      if (sometask == 0) break;      if (sometask == PX_threadId) {          //PTRACE(1, "tlibthrd\tIsTerminated(" << (void *)this << ") not dead yet");          return FALSE;      }  }  // didn't find it, it's dead  //PTRACE(1, "tlibthrd\tIsTerminated(" << (void *)this << ") = 0");  return TRUE;#else  return FALSE; // ENOCLUE#endif}// Mac OS X and Darwin 1.2 does not support pthread_kill() or sigwait()// so we cannot implement suspend and resume using signals. Instead we have a// partial implementation using a Semaphore.// As a result, we can create a thread in a suspended state and then 'resume'// it, but once it is going, we can no longer suspend it.// So, for Mac OS X, we will accept Resume() calls (or Suspend(FALSE))// but reject Suspend(TRUE) calls with an Assertion. This will indicate// to a user that we cannot Suspend threads on Mac OS Xvoid PThread::Suspend(BOOL susp){  OSStatus err;  err = MPWaitOnSemaphore(PX_suspendMutex,kDurationForever);  PAssert(err == 0, "MPWaitOnSemaphore failed");  if (susp) {    // Suspend - warn the user with an Assertion    PAssertAlways("Cannot suspend threads on Mac OS X due to lack of pthread_kill()");  }  // if resuming, then see if to really resume  else if (PX_suspendCount > 0) {    PX_suspendCount--;    if (PX_suspendCount == 0)  {      suspend_semaphore->Signal();    }  }  err = MPSignalSemaphore(PX_suspendMutex);  PAssert( err == 0, "MPSignalSemaphore failed");}void PThread::Resume(){  Suspend(FALSE);}BOOL PThread::IsSuspended() const{  OSStatus err;  if (IsTerminated())    return FALSE;  err = MPWaitOnSemaphore(PX_suspendMutex, kDurationForever);  PAssert(err == 0, "MPWaitOnSemaphore failed");  BOOL suspended = PX_suspendCount > 0;  err = MPSignalSemaphore(PX_suspendMutex);  PAssert(err == 0, "MPSignalSemaphore failed");  return suspended;}void PThread::SetAutoDelete(AutoDeleteFlag deletion){  PAssert(deletion != AutoDeleteThread || this != &PProcess::Current(), PLogicError);  autoDelete = deletion == AutoDeleteThread;}void PThread::SetPriority(Priority /*priorityLevel*/){}PThread::Priority PThread::GetPriority() const{  return LowestPriority;}void PThread::Yield(){  ::sleep(0);}PThread * PThread::Current(){  PProcess & process = PProcess::Current();  process.threadMutex.Wait();  PThread * thread = process.activeThreads.GetAt((unsigned)MPCurrentTaskID());  process.threadMutex.Signal();  return PAssertNULL(thread);}void PThread::Sleep(const PTimeInterval & timeout){    AbsoluteTime expiry;    Duration delta = kDurationForever;        if (timeout != PMaxTimeInterval) {        delta = timeout.GetMilliSeconds();    }    expiry = AddDurationToAbsolute(delta, UpTime());        (void)MPDelayUntil(&expiry);}void PThread::WaitForTermination() const{  PAssert(Current() != this, "Waiting for self termination!");    PXAbortBlock();  while (!IsTerminated()) {    PAssert(PX_signature == kMPThreadSig, "bad signature in living thread");    Current()->Sleep(10);#ifdef DEBUG_THREADS    if (debug_mpthreads)        fprintf(stderr,"spinning for termination of thread %p\n", (void *)this);#endif      if (noHousekeeper) PollNotificationQueue(kDurationImmediate);  }}BOOL PThread::WaitForTermination(const PTimeInterval & maxWait) const{  PAssert(Current() != this, "Waiting for self termination!");    //PTRACE(1, "tlibthrd\tWaitForTermination(delay)");  PXAbortBlock();  PTimer timeout = maxWait;  while (!IsTerminated()) {    if (timeout == 0)      return FALSE;    Current()->Sleep(10);  }  return TRUE;}///////////////////////////////////////////////////////////////////////////////PSemaphore::PSemaphore(unsigned initial, unsigned maxCount){    OSStatus err = MPCreateSemaphore(maxCount, initial, &semId);    PAssert(err == 0, "MPCreateSemaphore failed");    PAssert((long)semId != 0 && (long)semId != -1, "stupid semId");}PSemaphore::~PSemaphore(){    OSStatus err = MPDeleteSemaphore(semId);    PAssert(err == 0, "MPDeleteSemaphore failed");    *(long *)&semId = -1;}void PSemaphore::Wait(){    assert((long)semId != 0);    assert((long)semId != -1);        PAssert((long)semId != -1, "wait on destructed PSemaphore");    PAssert((long)semId != 0, "semId stomped");    OSStatus err = MPWaitOnSemaphore(semId, kDurationForever);    PAssert(err == 0, "MPWaitOnSemaphore failed");}BOOL PSemaphore::Wait(const PTimeInterval & waitTime){  OSErr err = 0;      if (waitTime == PMaxTimeInterval) {    Wait();    return TRUE;  }  Duration timeout = waitTime.GetMilliSeconds();  if ((err = MPWaitOnSemaphore(semId, timeout)) == noErr)      return TRUE;  if (err == kMPTimeoutErr)      return FALSE;  PAssert(err == 0, psprintf("timed wait error = %i", err));  return FALSE;}void PSemaphore::Signal(){    OSStatus err = MPSignalSemaphore(semId);    // was it already signalled?    if (err == kMPInsufficientResourcesErr) err = 0;    PAssert(err == 0, "MPSignalSemaphore failed");}BOOL PSemaphore::WillBlock() const{    OSStatus err = MPWaitOnSemaphore(semId, kDurationImmediate);    if (err == kMPTimeoutErr)        return TRUE;    PAssert(err == 0, psprintf("timed wait error = %i", err));    (void)MPSignalSemaphore(semId);    return FALSE;}// Ideally, a PMutex would contain an MPCriticalSection instead of a// semaphore, but the class derivation is outside the machine-specific// code, and I'm unwilling to do something gross like implement a bogus// constructor for PSemaphore which doesn't allocate a semaphore.PMutex::PMutex()  : PSemaphore(1, 1){}void PMutex::Wait(){	PSemaphore::Wait();}BOOL PMutex::Wait(const PTimeInterval & timeout){	return PSemaphore::Wait(timeout);}void PMutex::Signal(){	PSemaphore::Signal();}BOOL PMutex::WillBlock() const {	return PSemaphore::WillBlock();}PSyncPoint::PSyncPoint()  : PSemaphore(0, 1){}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -