📄 nucleusthread.cxx
字号:
/*
* NucleusThread.cxx
*
* pwlib's PThread as implemented for Nucleus++
*
* Copyright (c) 1999 ISDN Communications Ltd
*
* Author: Chris Wayman Purvis
*
*/
#include <ptlib.h>
#include <ptlib/sockets.h>
#include "net/inc/externs.h"
#include "plus/nucleus.h"
#include "net/inc/socketd.h" /* socket interface structures */
#include "net/target.h"
#include "net/inc/tcpdefs.h"
#include <sys/socket.h>
const UNSIGNED pwNUTask::NUTimeSlicesPermitted = 5;
// Map from pwlib priority level to Nucleus priority level
static int const priorities[] =
{
66, // Lowest Priority
64, // Low Priority
62, // Normal Priority
60, // High Priority
10 // Highest Priority
};
#ifdef __NUCLEUS_MNT__
#define new PNEW
#endif
PThread::PThread(PINDEX stackSize, AutoDeleteFlag deletion,
Priority PriorityLevel,
const PString & ThreadName)
// Threads start in a singly-suspended state. That's the way it works.
: n_suspendCount(1)
{
PAssert(stackSize > 0, PInvalidParameter);
autoDelete = (deletion == AutoDeleteThread);
NucleusTask = new pwNUTask( stackSize,// Stack Size Requested
priorities[PriorityLevel],
// Map from pwlib level to Nucleus level
this,
ThreadName); // So it knows what to call back to!
STATUS stat = NucleusTask->Information(&NucleusTaskInfo);
PAssert(stat == NU_SUCCESS, "Failure to find TaskInfo block");
}
PThread::~PThread()
{
if (!IsTerminated())
{
Terminate();
}
delete NucleusTask;
}
void PThread::Restart()
{
PAssert(IsTerminated(), "Cannot restart running thread");
NucleusTask->Reset();
PAssertAlways("Reset, but not restarted...");
}
void PThread::Terminate()
{
PAssert(!IsTerminated(),
"Cannot terminate a thread which is already terminated");
STATUS stat = NucleusTask->Terminate();
PAssert(stat == NU_SUCCESS, "Invalid Task Pointer on Termination");
}
#if !P_USE_INLINES
// What a pfaff for something that's easy...
// Still, at last I've written a function I'm pretty confident will work!
PBoolean PThread::IsTerminated() const
{
#ifdef __NUCLEUS_MNT__
cout << "q";
#else
printf("q");
#endif
STATUS stat = NucleusTaskInfo->Update();
PAssert(stat == NU_SUCCESS, "Invalid Task Pointer on Termination Check");
return ((NucleusTaskInfo->taskStatus == NU_TERMINATED) || (NucleusTaskInfo->taskStatus == NU_FINISHED));
}
#endif
void PThread::WaitForTermination() const
{
while (!IsTerminated())
{
Current()->Sleep(10);
}
}
PBoolean PThread::WaitForTermination(const PTimeInterval & maxWait) const
{
PTimer timeout = maxWait;
while (!IsTerminated())
{
if (timeout == 0)
{
return PFalse;
}
Current()->Sleep(10);
}
return PTrue;
}
void PThread::Suspend(PBoolean susp)
{
STATUS stat;
if (susp)
{
if (++n_suspendCount != 1)
{
stat = NucleusTask->Suspend();
PAssert(stat == NU_SUCCESS, "Invalid Task Pointer on suspend");
}
}
else
{
Resume();
}
}
#if !P_USE_INLINES
void PThread::Resume()
{
switch (--n_suspendCount)
{
case -1:
PAssertAlways("Resuming thread that hasn't been suspended!");
n_suspendCount = 0;
break;
case 0:
{
STATUS stat = NucleusTask->Resume();
PAssert(stat == NU_SUCCESS, "Invalid Task Pointer on resume");
}
break;
default: // Already handled in switch statement
break;
}
}
PBoolean PThread::IsSuspended() const
{
return (n_suspendCount != 0);
}
void PThread::SetPriority(Priority priorityLevel)
{
((Task *)(NucleusTask))->ChangePriority(priorities[priorityLevel]);
}
PThread::Priority PThread::GetPriority() const
{
// TaskInfo * NucleusTaskInfo = 0;
// STATUS stat = NucleusTask->Information(&NucleusTaskInfo);
NucleusTaskInfo->Update();
PAssert(stat == NU_SUCCESS, "Invalid Task Pointer on GetPriority Request");
PBoolean FoundIt = PFalse;
for ( int i = LowestPriority;
i < NumPriorities;
++i)
{
if (NucleusTaskInfo->priority == priorities[i])
{
return (PThread::Priority)i;
}
}
PAssertAlways ("PriorityLevel not valid for pwlib task!");
return (PThread::Priority)NucleusTaskInfo->priority;
}
PThread * PThread::Current()
{
return ((pwNUTask *)Task::Current())->AssociatedPThread;
}
#endif
void PThread::Yield()
{
Task::Relinquish();
}
void PThread::InitialiseProcessThread()
{
//#pragma message("Anything to do in InitialiseProcessThread()? Or all in PProcess constructor?")
// Certainly need to do some of the thready stuff that's normally done in the
// (non-trivial) PThread constructor. Like starting the Nucleus thread!
autoDelete = PFalse;
NucleusTask = new pwNUTask( (UNSIGNED)2048, // Stack Size Requested
(OPTION)priorities[HighPriority],
// Map from pwlib level to Nucleus level
(PThread *)this,
"PWLIB");// So it knows what to call back to!
NucleusTaskInfo = new TaskInfo();
}
void PThread::Sleep(const PTimeInterval & time)
{
Task::Sleep(((time.GetInterval())/PTimer::Resolution()));
}
#if 0
// Unnecessary as Nucleus has threads!
PBoolean PThread::IsNoLongerBlocked()
{
STATUS stat = NucleusTaskInfo->Update();
PAssert(stat == NU_SUCCESS, "Invalid Task Pointer on Blocking Check");
PAssert(NucleusTaskInfo->taskStatus != NU_TERMINATED,
"Operation on terminated thread");
// No longer blocked iff ready to go!
return (NucleusTaskInfo->taskStatus) == NU_READY;
}
#endif
PThread::PThread()
: n_suspendCount(1)
{
//Should all be done in IsNoLongerBlocked - but may even be unnecessary there!
}
// Stolen out of tlib threads
int PThread::PXBlockOnIO(int handle, int type, const PTimeInterval & timeout)
{
// make sure we flush the buffer before doing a write
fd_set tmp_rfd, tmp_wfd, tmp_efd;
fd_set * read_fds = &tmp_rfd;
fd_set * write_fds = &tmp_wfd;
fd_set * exception_fds = &tmp_efd;
FD_ZERO(read_fds);
FD_ZERO(write_fds);
FD_ZERO(exception_fds);
switch (type) {
case PChannel::PXReadBlock:
case PChannel::PXAcceptBlock:
FD_SET(handle, read_fds);
break;
case PChannel::PXWriteBlock:
FD_SET(handle, write_fds);
break;
case PChannel::PXConnectBlock:
FD_SET(handle, write_fds);
FD_SET(handle, exception_fds);
break;
default:
PAssertAlways(PLogicError);
return 0;
}
struct timeval * tptr = NULL;
struct timeval timeout_val;
if (timeout != PMaxTimeInterval) {
static const PTimeInterval oneDay(0, 0, 0, 0, 1);
if (timeout < oneDay) {
timeout_val.tv_usec = (timeout.GetMilliSeconds() % 1000) * 1000;
timeout_val.tv_sec = timeout.GetSeconds();
tptr = &timeout_val;
}
}
int retval = ::select(handle+1, read_fds, write_fds, exception_fds, tptr);
PProcess::Current().PXCheckSignals();
return retval;
}
void pwNUTask::Entry()
{
PProcess & process = PProcess::Current();
process.OnThreadStart(*AssociatedPThread);
AssociatedPThread->Main();
process.OnThreadEnded(*AssociatedPThread);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -