📄 tlibbe.cxx
字号:
#endif
return 1;
}
if ( result == B_OK )
{
// thread is dead
return 1;
}
if ( result == B_BAD_THREAD_ID )
{
// thread has invalid id
return 1;
}
return 0; // ???
}
PThreadIdentifier PThread::GetCurrentThreadId(void)
{
return ::find_thread(NULL);
}
int PThread::PXBlockOnIO(int handle, int type, const PTimeInterval & timeout)
{
PTRACE(7, "PWLib\tPThread::PXBlockOnIO(" << handle << ',' << type << ')');
if ((handle < 0) || (handle >= PProcess::Current().GetMaxHandles())) {
PTRACE(2, "PWLib\tAttempt to use illegal handle in PThread::PXBlockOnIO, handle=" << handle);
errno = EBADF;
return -1;
}
// make sure we flush the buffer before doing a write
P_fd_set read_fds;
P_fd_set write_fds;
P_fd_set exception_fds;
int retval;
do {
switch (type) {
case PChannel::PXReadBlock:
case PChannel::PXAcceptBlock:
read_fds = handle;
write_fds.Zero();
exception_fds.Zero();
break;
case PChannel::PXWriteBlock:
read_fds.Zero();
write_fds = handle;
exception_fds.Zero();
break;
case PChannel::PXConnectBlock:
read_fds.Zero();
write_fds = handle;
exception_fds = handle;
break;
default:
PAssertAlways(PLogicError);
return 0;
}
// include the termination pipe into all blocking I/O functions
read_fds += unblockPipe[0];
P_timeval tval = timeout;
retval = ::select(PMAX(handle, unblockPipe[0])+1,
read_fds, write_fds, exception_fds, tval);
} while (retval < 0 && errno == EINTR);
if ((retval == 1) && read_fds.IsPresent(unblockPipe[0])) {
BYTE ch;
::read(unblockPipe[0], &ch, 1);
errno = EINTR;
retval = -1;
PTRACE(6, "PWLib\tUnblocked I/O");
}
return retval;
}
void PThread::PXAbortBlock(void) const
{
BYTE ch;
::write(unblockPipe[1], &ch, 1);
}
///////////////////////////////////////////////////////////////////////////////
// PProcess
PDECLARE_CLASS(PHouseKeepingThread, PThread)
public:
PHouseKeepingThread()
: PThread(1000, NoAutoDeleteThread, NormalPriority, "Housekeeper")
{ closing = FALSE; Resume(); }
void Main();
void SetClosing() { closing = TRUE; }
protected:
BOOL closing;
};
void PProcess::Construct()
{
maxHandles = FOPEN_MAX;
PTRACE(4, "PWLib\tMaximum per-process file handles is " << maxHandles);
::pipe(timerChangePipe);
// initialise the housekeeping thread
housekeepingThread = NULL;
CommonConstruct();
}
void PHouseKeepingThread::Main()
{
PProcess & process = PProcess::Current();
while (!closing) {
PTimeInterval delay = process.timers.Process();
int fd = process.timerChangePipe[0];
P_fd_set read_fds = fd;
P_timeval tval = delay;
if (::select(fd+1, read_fds, NULL, NULL, tval) == 1) {
BYTE ch;
::read(fd, &ch, 1);
}
process.PXCheckSignals();
}
}
void PProcess::SignalTimerChange()
{
if (housekeepingThread == NULL)
{
housekeepingThread = new PHouseKeepingThread;
}
BYTE ch;
write(timerChangePipe[1], &ch, 1);
}
BOOL PProcess::SetMaxHandles(int newMax)
{
return FALSE;
}
PProcess::~PProcess()
{
PreShutdown();
// Don't wait for housekeeper to stop if Terminate() is called from it.
if (housekeepingThread != NULL && PThread::Current() != housekeepingThread) {
housekeepingThread->SetClosing();
SignalTimerChange();
housekeepingThread->WaitForTermination();
delete housekeepingThread;
}
CommonDestruct();
}
///////////////////////////////////////////////////////////////////////////////
// PSemaphore
PSemaphore::PSemaphore(BOOL fNested) : mfNested(fNested)
{
}
PSemaphore::PSemaphore(unsigned initial, unsigned)
{
Create(initial);
}
void PSemaphore::Create(unsigned initial)
{
mOwner = ::find_thread(NULL);
PAssertOS(mOwner != B_BAD_THREAD_ID);
if(!mfNested)
{
mCount = initial;
semId = ::create_sem(initial, "PWLS");
PAssertOS(semId >= B_NO_ERROR);
#ifdef DEBUG_SEMAPHORES
sem_info info;
get_sem_info(semId, &info);
PError << "::create_sem (PSemaphore()), id: " << semId << ", this: " << this << ", count:" << info.count << endl;
#endif
}
else // Use BLocker
{
semId = (sem_id) new BLocker("PWLN", true); // PWLib use recursive locks. true for benaphore style, false for not
}
}
PSemaphore::~PSemaphore()
{
if(!mfNested)
{
status_t result = B_NO_ERROR;
PAssertOS(semId >= B_NO_ERROR);
// Transmit ownership of the semaphore to our thread
thread_id curThread = ::find_thread(NULL);
if(mOwner != curThread)
{
thread_info tinfo;
::get_thread_info(curThread, &tinfo);
::set_sem_owner(semId, tinfo.team);
mOwner = curThread;
}
#ifdef DEBUG_SEMAPHORES
sem_info info;
get_sem_info(semId, &info);
PError << "::delete_sem, id: " << semId << ", this: " << this << ", name: " << info.name << ", count:" << info.count;
#endif
// Deleting the semaphore id
result = ::delete_sem(semId);
#ifdef DEBUG_SEMAPHORES
if( result != B_NO_ERROR )
PError << "...delete_sem failed, error: " << strerror(result) << endl;
#endif
}
else // Use BLocker
{
delete (BLocker*) semId; // Thanks!
}
}
void PSemaphore::Wait()
{
if(!mfNested)
{
PAssertOS(semId >= B_NO_ERROR);
status_t result = B_NO_ERROR;
#ifdef DEBUG_SEMAPHORES
sem_info info;
get_sem_info(semId, &info);
PError << "::acquire_sem, id: " << semId << ", name: " << info.name << ", count:" << info.count << endl;
#endif
while((B_BAD_THREAD_ID != mOwner)
&& ((result = ::acquire_sem(semId)) == B_INTERRUPTED))
{
}
}
else
{
((BLocker*)semId)->Lock(); // Using class to support recursive locks
}
}
BOOL PSemaphore::Wait(const PTimeInterval & timeout)
{
PInt64 ms = timeout.GetMilliSeconds();
bigtime_t microseconds = ms * 1000;
status_t result = B_NO_ERROR;
if(!mfNested)
{
PAssertOS(semId >= B_NO_ERROR);
PAssertOS(timeout < PMaxTimeInterval);
#ifdef DEBUG_SEMAPHORES
sem_info info;
get_sem_info(semId, &info);
PError << "::acquire_sem_etc " << semId << ",this: " << this << ", name: " << info.name << ", count:" << info.count
<< ", ms: " << microseconds << endl;
#endif
while((B_BAD_THREAD_ID != mOwner)
&& ((result = ::acquire_sem_etc(semId, 1,
B_RELATIVE_TIMEOUT, microseconds)) == B_INTERRUPTED))
{
}
}
else
{
result = ((BLocker*)semId)->LockWithTimeout(microseconds); // Using BLocker class to support recursive locks
}
return ms == 0 ? FALSE : result == B_OK;
}
void PSemaphore::Signal()
{
if(!mfNested)
{
PAssertOS(semId >= B_NO_ERROR);
#ifdef DEBUG_SEMAPHORES
sem_info info;
get_sem_info(semId, &info);
PError << "::release_sem " << semId << ", this: " << this << ", name: " << info.name << ", count:" << info.count << endl;
#endif
::release_sem(semId);
}
else
{
((BLocker*)semId)->Unlock(); // Using BLocker class to support recursive locks
}
}
BOOL PSemaphore::WillBlock() const
{
if(!mfNested)
{
PAssertOS(semId >= B_NO_ERROR);
#ifdef DEBUG_SEMAPHORES
sem_info info;
get_sem_info(semId, &info);
PError << "::acquire_sem_etc (WillBlock) " << semId << ", this: " << this << ", name: " << info.name << ", count:" << info.count << endl;
#endif
status_t result = ::acquire_sem_etc(semId, 0, B_RELATIVE_TIMEOUT, 0);
return result == B_WOULD_BLOCK;
}
else
{
return mOwner == find_thread(NULL); // If we are in our own thread, we won't lock
}
}
///////////////////////////////////////////////////////////////////////////////
// PSyncPoint
PSyncPoint::PSyncPoint()
: PSemaphore(FALSE) // FALSE is semaphore based, TRUE means implemented through BLocker
{
PSemaphore::Create(0);
}
void PSyncPoint::Signal()
{
PSemaphore::Signal();
}
void PSyncPoint::Wait()
{
PSemaphore::Wait();
}
BOOL PSyncPoint::Wait(const PTimeInterval & timeout)
{
return PSemaphore::Wait(timeout);
}
BOOL PSyncPoint::WillBlock() const
{
return PSemaphore::WillBlock();
}
//////////////////////////////////////////////////////////////////////////////
// PMutex, derived from BLightNestedLocker
PMutex::PMutex()
: PSemaphore(TRUE) // TRUE means implemented through BLocker
{
PSemaphore::Create(0);
}
PMutex::PMutex(const PMutex&)
: PSemaphore(TRUE)
{
PAssertAlways("PMutex copy constructor not supported");
}
void PMutex::Signal()
{
PSemaphore::Signal();
}
void PMutex::Wait()
{
PSemaphore::Wait();
}
BOOL PMutex::Wait(const PTimeInterval & timeout)
{
return PSemaphore::Wait(timeout);
}
BOOL PMutex::WillBlock() const
{
return PSemaphore::WillBlock();
}
//////////////////////////////////////////////////////////////////////////////
// Extra functionality not found in BeOS
int seteuid(uid_t uid) { return 0; }
int setegid(gid_t gid) { return 0; }
///////////////////////////////////////////////////////////////////////////////
// Toolchain dependent stuff
#if (__GNUC_MINOR__ > 9)
#warning "Using gcc 2.95.x"
ostream& ostream::write(const char *s, streamsize n) { return write(s, (long) n); };
istream& istream::read(char *s, streamsize n) { return read(s, (long) n); };
#endif // gcc minor > 9
// End Of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -