📄 osutils.cxx
字号:
static unsigned PTraceLevelThreshold = 0;
static PTimeInterval ApplicationStartTick/* = PTimer::Tick()*/;
unsigned PTraceCurrentLevel;
static const char * PTrace_Filename = NULL;
static int PTrace_lastDayOfYear = 0;
void PTrace::SetStream(ostream * s)
{
#ifndef __NUCLEUS_PLUS__
if (s == NULL)
s = &cerr;
#endif
if (PTraceMutex == NULL)
PTraceStream = s;
else {
PWaitAndSignal m(*PTraceMutex);
PTraceStream = s;
}
}
void PTrace::SetNewStream(ostream * s, INT externalMutex)
{
#ifndef __NUCLEUS_PLUS__
if (s == NULL)
s = &cerr;
#endif
if (PTraceMutex != NULL)
{
delete PTraceMutex;
PTraceMutex = reinterpret_cast<PMutex*>(externalMutex);
}
PWaitAndSignal m(*PTraceMutex);
PTraceStream = s;
PTrace::ClearOptions(PTrace::SystemLogStream);
PTrace::ClearOptions(PTrace::DateAndTime);
PTrace::SetOptions( PTrace::Timestamp );
}
static void OpenTraceFile()
{
PFilePath fn(PTrace_Filename);
if ((PTraceOptions & PTrace::RotateDaily) != 0)
fn = PFilePath(fn.GetDirectory() + (fn.GetTitle() + PTime((PTraceOptions&PTrace::GMTTime) ? PTime::GMT : PTime::Local).AsString("yyyy_MM_dd") + fn.GetType()));
PTextFile * traceOutput;
if (PTraceOptions & PTrace::AppendToFile) {
traceOutput = new PTextFile(fn, PFile::ReadWrite);
traceOutput->SetPosition(0, PFile::End);
} else
traceOutput = new PTextFile(fn, PFile::WriteOnly);
if (traceOutput->IsOpen())
PTrace::SetStream(traceOutput);
else {
PTRACE(0, PProcess::Current().GetName() << "Could not open trace output file \"" << fn << '"');
delete traceOutput;
}
}
void PTrace::Initialise(unsigned level, const char * filename, unsigned options)
{
// If we have a tracing version, then open trace file and set modes
#if PTRACING
PProcess & process = PProcess::Current();
#endif
#ifndef _DEBUG
#undef PMEMORY_CHECK
#endif
#if PMEMORY_CHECK
int ignoreAllocations = -1;
#endif
PTrace_Filename = filename;
PTraceOptions = options;
if (options & RotateDaily)
PTrace_lastDayOfYear = PTime((PTraceOptions&GMTTime) ? PTime::GMT : PTime::Local).GetDayOfYear();
else
PTrace_lastDayOfYear = 0;
if (filename != NULL) {
#if PMEMORY_CHECK
ignoreAllocations = PMemoryHeap::SetIgnoreAllocations(TRUE) ? 1 : 0;
#endif
OpenTraceFile();
}
PTraceLevelThreshold = level;
PTRACE(1, process.GetName()
<< "\tVersion " << process.GetVersion(TRUE)
<< " by " << process.GetManufacturer()
<< " on " << process.GetOSClass() << ' ' << process.GetOSName()
<< " (" << process.GetOSVersion() << '-' << process.GetOSHardware()
<< ") at " << PTime().AsString("yyyy/M/d h:mm:ss.uuu"));
#if PMEMORY_CHECK
if (ignoreAllocations >= 0)
PMemoryHeap::SetIgnoreAllocations(ignoreAllocations != 0);
#endif
}
void PTrace::SetOptions(unsigned options)
{
PTraceOptions |= options;
}
void PTrace::ClearOptions(unsigned options)
{
PTraceOptions &= ~options;
}
unsigned PTrace::GetOptions()
{
return PTraceOptions;
}
void PTrace::SetLevel(unsigned level)
{
PTraceLevelThreshold = level;
}
unsigned PTrace::GetLevel()
{
return PTraceLevelThreshold;
}
BOOL PTrace::CanTrace(unsigned level)
{
return level <= PTraceLevelThreshold;
}
ostream & PTrace::Begin(unsigned level, const char * fileName, int lineNum)
{
if (PTraceMutex == NULL) {
PAssertAlways("Cannot use PTRACE before PProcess constructed.");
return *PTraceStream;
}
if (level == UINT_MAX)
return *PTraceStream;
PTraceMutex->Wait();
// Save log level for this message so End() function can use. This is
// protected by the PTraceMutex
PTraceCurrentLevel = level;
if ((PTrace_Filename != NULL) && (PTraceOptions&RotateDaily) != 0) {
int day = PTime((PTraceOptions&GMTTime) ? PTime::GMT : PTime::Local).GetDayOfYear();
if (day != PTrace_lastDayOfYear) {
delete PTraceStream;
PTraceStream = NULL;
OpenTraceFile();
if (PTraceStream == NULL) {
PTraceMutex->Signal();
return *PTraceStream;
}
}
}
if ((PTraceOptions&SystemLogStream) == 0) {
if ((PTraceOptions&DateAndTime) != 0) {
PTime now;
*PTraceStream << now.AsString("yyyy/MM/dd hh:mm:ss.uuu\t", (PTraceOptions&GMTTime) ? PTime::GMT : PTime::Local);
}
if ((PTraceOptions&Timestamp) != 0)
*PTraceStream << setprecision(3) << setw(10) << (PTimer::Tick()-ApplicationStartTick) << '\t';
if ((PTraceOptions&Thread) != 0) {
PThread * thread = PThread::Current();
if (thread == NULL)
*PTraceStream << "ThreadID=0x"
<< setfill('0') << hex << setw(8)
<< PThread::GetCurrentThreadId()
<< setfill(' ') << dec;
else {
PString name = thread->GetThreadName();
if (name.GetLength() <= 23)
*PTraceStream << setw(23) << name;
else
*PTraceStream << name.Left(10) << "..." << name.Right(10);
}
*PTraceStream << '\t';
}
if ((PTraceOptions&ThreadAddress) != 0)
*PTraceStream << hex << setfill('0')
<< setw(7) << (void *)PThread::Current()
<< dec << setfill(' ') << '\t';
}
if ((PTraceOptions&TraceLevel) != 0)
*PTraceStream << level << '\t';
if ((PTraceOptions&FileAndLine) != 0 && fileName != NULL) {
const char * file = strrchr(fileName, '/');
if (file != NULL)
file++;
else {
file = strrchr(fileName, '\\');
if (file != NULL)
file++;
else
file = fileName;
}
*PTraceStream << setw(16) << file << '(' << lineNum << ")\t";
}
*PTraceStream << "PWL: [CID=0x0000] ";
return *PTraceStream;
}
ostream & PTrace::End(ostream & s)
{
/* Only output if there is something to output, this prevents some blank trace
entries from appearing under some patholgical conditions. Unfortunately if
stderr is used the unitbuf flag causes the out_waiting() not to work so we
must suffer with blank lines in that case.
*/
#if 0
#ifndef P_LINUX
::streambuf & rb = *s.rdbuf();
if (((s.flags()&ios::unitbuf) != 0) ||
#ifdef __USE_STL__
rb.pubseekoff(0, ios::cur, ios::out) > 0
#else
rb.out_waiting() > 0
#endif
)
#endif
#endif
{
if ((PTraceOptions&SystemLogStream) != 0) {
// Get the trace level for this message and set the stream width to that
// level so that the PSystemLog can extract the log level back out of the
// ios structure. There could be portability issues with this though it
// should work pretty universally.
s.width(PTraceCurrentLevel+1);
s.flush();
}
else
s << endl;
}
PTraceMutex->Signal();
return s;
}
PTrace::Block::Block(const char * fileName, int lineNum, const char * traceName)
{
file = fileName;
line = lineNum;
name = traceName;
if ((PTraceOptions&Blocks) != 0) {
PThread * thread = PThread::Current();
thread->traceBlockIndentLevel += 2;
ostream & s = PTrace::Begin(1, file, line);
s << "B-Entry\t";
for (unsigned i = 0; i < thread->traceBlockIndentLevel; i++)
s << '=';
s << "> " << name << PTrace::End;
}
}
PTrace::Block::~Block()
{
if ((PTraceOptions&Blocks) != 0) {
PThread * thread = PThread::Current();
ostream & s = PTrace::Begin(1, file, line);
s << "B-Exit\t<";
for (unsigned i = 0; i < thread->traceBlockIndentLevel; i++)
s << '=';
s << ' ' << name << PTrace::End;
thread->traceBlockIndentLevel -= 2;
}
}
///////////////////////////////////////////////////////////////////////////////
// PDirectory
void PDirectory::CloneContents(const PDirectory * d)
{
CopyContents(*d);
}
///////////////////////////////////////////////////////////////////////////////
// PTimeInterval
DWORD PTimeInterval::GetInterval() const
{
if (milliseconds <= 0)
return 0;
if (milliseconds >= UINT_MAX)
return UINT_MAX;
return (DWORD)milliseconds;
}
///////////////////////////////////////////////////////////////////////////////
// PTimer
PTimer::PTimer(long millisecs, int seconds, int minutes, int hours, int days)
: resetTime(millisecs, seconds, minutes, hours, days)
{
Construct();
}
PTimer::PTimer(const PTimeInterval & time)
: resetTime(time)
{
Construct();
}
void PTimer::Construct()
{
state = Starting;
timerList = PProcess::Current().GetTimerList();
timerList->listMutex.Wait();
timerList->Append(this);
timerList->listMutex.Signal();
timerList->processingMutex.Wait();
StartRunning(TRUE);
}
PTimer & PTimer::operator=(DWORD milliseconds)
{
timerList->processingMutex.Wait();
resetTime.SetInterval(milliseconds);
StartRunning(oneshot);
return *this;
}
PTimer & PTimer::operator=(const PTimeInterval & time)
{
timerList->processingMutex.Wait();
resetTime = time;
StartRunning(oneshot);
return *this;
}
PTimer::~PTimer()
{
timerList->listMutex.Wait();
timerList->Remove(this);
BOOL isCurrentTimer = this == timerList->currentTimer;
timerList->listMutex.Signal();
// Make sure that the OnTimeout for this timer has completed before
// destroying the timer
if (isCurrentTimer) {
timerList->inTimeoutMutex.Wait();
timerList->inTimeoutMutex.Signal();
}
}
void PTimer::SetInterval(PInt64 milliseconds,
long seconds,
long minutes,
long hours,
int days)
{
timerList->processingMutex.Wait();
resetTime.SetInterval(milliseconds, seconds, minutes, hours, days);
StartRunning(oneshot);
}
void PTimer::RunContinuous(const PTimeInterval & time)
{
timerList->processingMutex.Wait();
resetTime = time;
StartRunning(FALSE);
}
void PTimer::StartRunning(BOOL once)
{
PTimeInterval::operator=(resetTime);
oneshot = once;
state = (*this) != 0 ? Starting : Stopped;
if (IsRunning())
PProcess::Current().SignalTimerChange();
// This must have been set by the caller
timerList->processingMutex.Signal();
}
void PTimer::Stop()
{
timerList->processingMutex.Wait();
state = Stopped;
milliseconds = 0;
BOOL isCurrentTimer = this == timerList->currentTimer;
timerList->processingMutex.Signal();
// Make sure that the OnTimeout for this timer has completed before
// retruning from Stop() function,
if (isCurrentTimer) {
timerList->inTimeoutMutex.Wait();
timerList->inTimeoutMutex.Signal();
}
}
void PTimer::Pause()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -