📄 tlibbe.cxx
字号:
/* * tlibbe.cxx * * Thread library implementation for BeOS * * Portable Windows Library * * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is Portable Windows Library. * * The Initial Developer of the Original Code is Equivalence Pty. Ltd. * * Portions are Copyright (c) 1993-1998 Equivalence Pty. Ltd. * * Portions are Copyright (C) 1993 Free Software Foundation, Inc. * All Rights Reserved. * * Contributor(s): Yuri Kiryanov, ykiryanov at users.sourceforge.net * * $Log: tlibbe.cxx,v $ * Revision 1.33 2004/10/26 18:29:41 ykiryanov * Added ostream::write and istream::read with 2nd param as streamsize to please * New toolchain * * Revision 1.32 2004/07/11 07:56:36 csoutheren * Applied jumbo VxWorks patch, thanks to Eize Slange * * Revision 1.31 2004/05/30 04:48:15 ykiryanov * Sync point is better when semaphore based * * Revision 1.30 2004/05/24 04:17:16 ykiryanov * Made PSyncPoint::Wait to return FALSE if called with timeout 0 * * Revision 1.29 2004/05/23 22:20:37 ykiryanov * Got rid of 2 housekeeper thread problem * * Revision 1.28 2004/05/21 00:49:16 csoutheren * Added PreShutdown to ~PProcess * * Revision 1.27 2004/05/02 18:00:54 ykiryanov * Renamed unblock pipe to make code compatible with socket code * * Revision 1.26 2004/05/02 16:59:09 ykiryanov * Fixed assert in setting priority to threads * * Revision 1.25 2004/04/30 16:10:20 ykiryanov * Added PMutex code based on BLocker to support recursive locks * * Revision 1.24 2004/04/25 21:51:37 ykiryanov * Cleaned up thread termination act. Very cool * * Revision 1.23 2004/04/25 04:32:37 ykiryanov * Fixed very old bug - no get thread id code in InitialiseProcessThread * * Revision 1.22 2004/04/18 00:23:40 ykiryanov * Rearranged code to be more reliable. We nearly there * * Revision 1.21 2004/04/02 03:17:19 ykiryanov * New version, improved * * Revision 1.20 2004/02/23 23:40:42 ykiryanov * Added missing constructor for PMutex * * Revision 1.19 2004/02/23 21:23:09 ykiryanov * Removed assert line to enable semaphore constructor * * Revision 1.18 2004/02/23 20:37:17 ykiryanov * Changed function definition PXBlockIO to prototype one * * Revision 1.17 2004/02/23 18:10:39 ykiryanov * Added a parameter to semaphore constructor to avoid ambiguity * * Revision 1.16 2004/02/23 00:02:20 ykiryanov * Changed my e-mail to ykiryanov at users.sourceforge.net. Just in case someone wants to collaborate * * Revision 1.15 2004/02/22 23:59:28 ykiryanov * Added missing functions: PProcess::SetMaxHandles(), PThread::GetCurrentThreadId(), * PThread::PXAbortBlock(), PSyncPoint::Signal(), ::Wait(), ::Wait(timeout), ::WillBlock() * * Revision 1.14 2004/02/22 04:35:04 ykiryanov * Removed PMutex desctructor * * Revision 1.13 2003/02/26 01:13:18 robertj * Fixed race condition where thread can terminatebefore an IsSuspeded() call * occurs and cause an assert, thanks Sebastian Meyer * * Revision 1.12 2001/06/30 06:59:07 yurik * Jac Goudsmit from Be submit these changes 6/28. Implemented by Yuri Kiryanov * * Revision 1.11 2001/03/07 06:57:32 yurik * Changed email to current one * * Revision 1.10 2001/01/16 12:32:06 rogerh * Remove duplicate SetAutoDelete() function. Submitted by * Jac Goudsmit <jac_goudsmit@yahoo.com> * * */class PThread;class PProcess;class PSemaphore;class PSyncPoint;class PMutex; #include <ptlib.h>#include <ptlib/socket.h>#ifdef B_ZETA_VERSION #include <posix/rlimit.h>#endif // Zeta// For class BLocker#include <be/support/Locker.h>int PX_NewHandle(const char *, int);#define DEBUG_SEMAPHORES1 1//////////////////////////////////////////////////////////////////////////////// Threadsstatic int const priorities[] = { 1, // Lowest priority is 1. 0 is not B_LOW_PRIORITY, B_NORMAL_PRIORITY, B_DISPLAY_PRIORITY, B_URGENT_DISPLAY_PRIORITY,};int32 PThread::ThreadFunction(void * threadPtr){ PThread * thread = (PThread *)PAssertNULL(threadPtr); PProcess & process = PProcess::Current(); process.threadMutex.Wait(); process.activeThreads.SetAt((unsigned) thread->mId, thread); process.threadMutex.Signal(); thread->Main(); return 0;}PThread::PThread() : autoDelete(TRUE), mId(B_BAD_THREAD_ID), mPriority(B_NORMAL_PRIORITY), mStackSize(0), mSuspendCount(0){}void PThread::InitialiseProcessThread(){ autoDelete = FALSE; mId = find_thread(NULL); mPriority = B_NORMAL_PRIORITY; mStackSize = 0; mSuspendCount = 1; PAssert(::pipe(unblockPipe) == 0, "Pipe creation failed in InitialiseProcessThread!"); PAssertOS(unblockPipe[0]); PAssertOS(unblockPipe[1]); ((PProcess *)this)->activeThreads.DisallowDeleteObjects(); ((PProcess *)this)->activeThreads.SetAt(mId, this);}PThread::PThread(PINDEX stackSize, AutoDeleteFlag deletion, Priority priorityLevel, const PString & name) : mId(B_BAD_THREAD_ID), mPriority(B_NORMAL_PRIORITY), mStackSize(0), mSuspendCount(0){ PAssert(stackSize > 0, PInvalidParameter); autoDelete = deletion == AutoDeleteThread; mId = ::spawn_thread(ThreadFunction, // Function (const char*) name, // Name priorities[priorityLevel], // Priority (void *) this); // Pass this as cookie PAssertOS(mId >= B_NO_ERROR); mSuspendCount = 1; mStackSize = stackSize; mPriority = priorities[priorityLevel]; threadName.sprintf(name, mId); ::rename_thread(mId, (const char*) threadName); // real, unique name - with id PAssert(::pipe(unblockPipe) == 0, "Pipe creation failed in PThread constructor"); PX_NewHandle("Thread unblock pipe", PMAX(unblockPipe[0], unblockPipe[1]));}PThread * PThread::Current(){ PProcess & process = PProcess::Current(); process.threadMutex.Wait(); PThread * thread = process.activeThreads.GetAt((unsigned)find_thread(NULL)); process.threadMutex.Signal(); return thread; }PThread::~PThread(){ // if we are not process, remove this thread from the active thread list PProcess & process = PProcess::Current(); if(process.GetThreadId() != GetThreadId()) { process.threadMutex.Wait(); process.activeThreads.RemoveAt((unsigned) mId); process.threadMutex.Signal(); } if (!IsTerminated()) Terminate(); ::close(unblockPipe[0]); ::close(unblockPipe[1]);}void PThread::Restart(){ if(!IsTerminated()) return; mId = ::spawn_thread(ThreadFunction, // Function "PWLT", // Name mPriority, (void *) this); // Pass this as cookie PAssertOS(mId >= B_NO_ERROR); threadName.sprintf("PWLib Thread %d", mId); ::rename_thread(mId, (const char*) threadName); // real, unique name - with id}void PThread::Terminate(){ if(mStackSize <=0) return; if(mId == find_thread(NULL)) { ::exit_thread(0); return; } if(IsTerminated()) return; PXAbortBlock(); WaitForTermination(20); if(mId > B_BAD_THREAD_ID) ::kill_thread(0);}BOOL PThread::IsTerminated() const{ return mId == B_BAD_THREAD_ID;}void PThread::WaitForTermination() const{ WaitForTermination(PMaxTimeInterval);}BOOL PThread::WaitForTermination(const PTimeInterval & /*maxWait*/) const // Fix timeout{ status_t result = B_NO_ERROR; status_t exit_value = B_NO_ERROR; result = ::wait_for_thread(mId, &exit_value); if ( result == B_INTERRUPTED ) { // thread was killed. return TRUE; } if ( result == B_OK ) { // thread is dead #ifdef DEBUG_THREADS PError << "B_OK" << endl; #endif return TRUE; } if ( result == B_BAD_THREAD_ID ) { // thread has invalid id return TRUE; } return FALSE;}void PThread::Suspend(BOOL susp){ PAssert(!IsTerminated(), "Operation on terminated thread"); if (susp) { status_t result = ::suspend_thread(mId); if(B_OK == result) ::atomic_add(&mSuspendCount, 1); PAssert(result == B_OK, "Thread don't want to be suspended"); } else Resume();}void PThread::Resume(){ PAssert(!IsTerminated(), "Operation on terminated thread"); status_t result = ::resume_thread(mId); if(B_OK == result) ::atomic_add(&mSuspendCount, -1); PAssert(result == B_NO_ERROR, "Thread doesn't want to resume");}BOOL PThread::IsSuspended() const{ return (mSuspendCount > 0);}void PThread::SetAutoDelete(AutoDeleteFlag deletion){ PAssert(deletion != AutoDeleteThread || this != &PProcess::Current(), PLogicError); autoDelete = deletion == AutoDeleteThread;}void PThread::SetPriority(Priority priorityLevel){ PAssert(!IsTerminated(), "Operation on terminated thread"); mPriority = priorities[priorityLevel]; status_t result = ::set_thread_priority(mId, mPriority ); if(result != B_OK) PTRACE(0, "Changing thread priority failed, error " << strerror(result) << endl);}PThread::Priority PThread::GetPriority() const{ if(!IsTerminated()) { switch (mPriority) { case 0 : return LowestPriority; case B_LOW_PRIORITY : return LowPriority; case B_NORMAL_PRIORITY : return NormalPriority; case B_DISPLAY_PRIORITY : return HighPriority; case B_URGENT_DISPLAY_PRIORITY : return HighestPriority; } PAssertAlways(POperatingSystemError); } return LowestPriority;}void PThread::Yield(){ // we just sleep for long enough to cause a reschedule (100 microsec) ::snooze(100);}void PThread::Sleep( const PTimeInterval & delay ) // Time interval to sleep for.{ bigtime_t microseconds = delay == PMaxTimeInterval ? B_INFINITE_TIMEOUT : (delay.GetMilliSeconds() * 1000 ); status_t result = ::snooze( microseconds ) ; // delay in ms, snooze in microsec PAssert(result == B_OK, "Thread has insomnia");}int PThread::PXBlockOnChildTerminate(int pid, const PTimeInterval & /*timeout*/) // Fix timeout{ status_t result = B_NO_ERROR; status_t exit_value = B_NO_ERROR; result = ::wait_for_thread(pid, &exit_value); if ( result == B_INTERRUPTED ) { // thread was killed. #ifdef DEBUG_THREADS PError << "B_INTERRUPTED" << endl; #endif return 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -