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

📄 osutils.cxx

📁 opal的ptlib c++源程序 可以从官方网站上下载
💻 CXX
📖 第 1 页 / 共 4 页
字号:
/*
 * osutils.cxx
 *
 * Operating System utilities.
 *
 * Portable Windows Library
 *
 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
 *
 * 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 Free Software Foundation, Inc.
 * All Rights Reserved.
 *
 * Contributor(s): ______________________________________.
 *
 * $Revision: 19649 $
 * $Author: csoutheren $
 * $Date: 2008-03-03 02:04:00 +0000 (Mon, 03 Mar 2008) $
 */

#include <ptlib.h>
#include <vector>
#include <map>

#include <ctype.h>
#include <ptlib/pfactory.h>
#include <ptlib/pprocess.h>

#ifdef _WIN32
#include <ptlib/msos/ptlib/debstrm.h>
#endif

#ifdef __MACOSX__
namespace PWLibStupidOSXHacks {
  extern int loadShmVideoStuff;
  extern int loadCoreAudioStuff;
  extern int loadFakeVideoStuff;
};
#endif

class PSimpleThread : public PThread
{
    PCLASSINFO(PSimpleThread, PThread);
  public:
    PSimpleThread(
      const PNotifier & notifier,
      INT parameter,
      AutoDeleteFlag deletion,
      Priority priorityLevel,
      const PString & threadName,
      PINDEX stackSize
    );
    void Main();
  protected:
    PNotifier callback;
    INT parameter;
};


#ifndef __NUCLEUS_PLUS__
static ostream * PErrorStream = &cerr;
#else
static ostream * PErrorStream = NULL;
#endif

ostream & PGetErrorStream()
{
  return *PErrorStream;
}


void PSetErrorStream(ostream * s)
{
#ifndef __NUCLEUS_PLUS__
  PErrorStream = s != NULL ? s : &cerr;
#else
  PErrorStream = s;
#endif
}

//////////////////////////////////////////////////////////////////////////////

#if PTRACING

class PTraceInfo
{
  /* NOTE you cannot have any complex types in this structure. Anything
     that might do an asert or PTRACE will crash due to recursion.
   */

public:
  unsigned        currentLevel;
  unsigned        options;
  unsigned        thresholdLevel;
  const char    * filename;
  ostream       * stream;
  PTimeInterval   startTick;
  const char    * rolloverPattern;
  unsigned        lastDayOfYear;
  ios::fmtflags   oldStreamFlags;
  std::streamsize oldPrecision;

#if defined(_WIN32)
  CRITICAL_SECTION mutex;
  void InitMutex() { InitializeCriticalSection(&mutex); }
  void Lock()      { EnterCriticalSection(&mutex); }
  void Unlock()    { LeaveCriticalSection(&mutex); }
#elif defined(P_PTHREADS) && P_HAS_RECURSIVE_MUTEX
  pthread_mutex_t mutex;
  void InitMutex() {
    // NOTE this should actually guard against various errors
    // returned.
    pthread_mutexattr_t attr;
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr,
#if P_HAS_RECURSIVE_MUTEX == 2
PTHREAD_MUTEX_RECURSIVE
#else
PTHREAD_MUTEX_RECURSIVE_NP
#endif
    );
    pthread_mutex_init(&mutex, &attr);
    pthread_mutexattr_destroy(&attr);
  }
  void Lock()      { pthread_mutex_lock(&mutex); }
  void Unlock()    { pthread_mutex_unlock(&mutex); }
#else
  PMutex * mutex;
  void InitMutex() { mutex = new PMutex; }
  void Lock()      { mutex->Wait(); }
  void Unlock()    { mutex->Signal(); }
#endif



  PTraceInfo()
    : currentLevel(0)
    , filename(NULL)
#ifdef __NUCLEUS_PLUS__
    , stream(NULL)
#else
    , stream(&cerr)
#endif
    , startTick(PTimer::Tick())
    , rolloverPattern("yyyy_MM_dd")
    , lastDayOfYear(0)
    , oldStreamFlags(ios::left)
    , oldPrecision(0)
  {
    InitMutex();

    const char * env = getenv("PWLIB_TRACE_STARTUP"); // Backward compatibility test
    if (env == NULL) 
      env = getenv("PTLIB_TRACE_STARTUP"); // Backward compatibility test
    if (env != NULL) {
      thresholdLevel = atoi(env);
      options = PTrace::Blocks | PTrace::Timestamp | PTrace::Thread | PTrace::FileAndLine;
    }
    else {
      env = getenv("PWLIB_TRACE_LEVEL");
      if (env == NULL)
        env = getenv("PTLIB_TRACE_LEVEL");
      thresholdLevel = env != NULL ? atoi(env) : 0;

      env = getenv("PWLIB_TRACE_OPTIONS");
      if (env == NULL)
        env = getenv("PTLIB_TRACE_OPTIONS");
      options = env != NULL ? atoi(env) : PTrace::FileAndLine;
    }
    env = getenv("PWLIB_TRACE_FILE");
    if (env == NULL)
      env = getenv("PTLIB_TRACE_FILE");

    OpenTraceFile(env);
  }

  static PTraceInfo & Instance()
  {
    static PTraceInfo info;
    return info;
  }

  void SetStream(ostream * newStream)
  {
#ifndef __NUCLEUS_PLUS__
    if (newStream == NULL)
      newStream = &cerr;
#endif

    Lock();

    if (stream != &cerr && stream != &cout)
      delete stream;
    stream = newStream;

    Unlock();
  }

  void OpenTraceFile(const char * newFilename)
  {
    if (newFilename != NULL)
      filename = newFilename;

    if (filename == NULL)
      return;

    PMEMORY_IGNORE_ALLOCATIONS_FOR_SCOPE;

    if (strcasecmp(filename, "stderr") == 0)
      SetStream(&cerr);
    else if (strcasecmp(filename, "stdout") == 0)
      SetStream(&cout);
#ifdef _WIN32
    else if (strcasecmp(filename, "DEBUGSTREAM") == 0)
      SetStream(new PDebugStream);
#endif
    else {
      PFilePath fn(filename);
      fn.Replace("%P", PString((unsigned int) PProcess::Current().GetProcessID()));
     
      if ((options & PTrace::RotateDaily) != 0)
      {
          PTime now;
          fn = PFilePath(fn.GetDirectory() + fn.GetTitle() + now.AsString(rolloverPattern, ((options&PTrace::GMTTime) ? PTime::GMT : PTime::Local)) + fn.GetType());
      }

      PTextFile * traceOutput;
      if (options & PTrace::AppendToFile) {
        traceOutput = new PTextFile(fn, PFile::ReadWrite);
        traceOutput->SetPosition(0, PFile::End);
      }
      else 
        traceOutput = new PTextFile(fn, PFile::WriteOnly);

      if (traceOutput->IsOpen())
        SetStream(traceOutput);
      else {
        PTRACE(0, PProcess::Current().GetName() << "Could not open trace output file \"" << fn << '"');
        delete traceOutput;
      }
    }
  }
};


void PTrace::SetStream(ostream * s)
{
  PTraceInfo::Instance().SetStream(s);
}

void PTrace::Initialise(
    unsigned level,
    const char * filename,
    unsigned options
)
{
  Initialise(level, filename, NULL, options);
}

void PTrace::Initialise(unsigned level, const char * filename, const char * rolloverPattern, unsigned options)
{
  PTraceInfo & info = PTraceInfo::Instance();

  info.options = options;
  info.thresholdLevel = level;
  info.rolloverPattern = rolloverPattern != NULL ? rolloverPattern : "yyyy_MM_dd";
  // Does PTime::GetDayOfYear() etc. want to take zone param like PTime::AsString() to switch 
  // between os_gmtime and os_localtime?
  info.lastDayOfYear = (options & RotateDaily) != 0 ? PTime().GetDayOfYear() : 0;

  info.OpenTraceFile(filename);

#if PTRACING
  PProcess & process = PProcess::Current();
  Begin(0, "", 0) << "\tVersion " << process.GetVersion(PTrue)
                  << " by " << process.GetManufacturer()
                  << " on " << process.GetOSClass() << ' ' << process.GetOSName()
                  << " (" << process.GetOSVersion() << '-' << process.GetOSHardware()
                  << ") at " << PTime().AsString("yyyy/M/d h:mm:ss.uuu")
                  << End;
#endif

}


void PTrace::SetOptions(unsigned options)
{
  PTraceInfo::Instance().options |= options;
}


void PTrace::ClearOptions(unsigned options)
{
  PTraceInfo::Instance().options &= ~options;
}


unsigned PTrace::GetOptions()
{
  return PTraceInfo::Instance().options;
}


void PTrace::SetLevel(unsigned level)
{
  PTraceInfo::Instance().thresholdLevel = level;
}


unsigned PTrace::GetLevel()
{
  return PTraceInfo::Instance().thresholdLevel;
}


PBoolean PTrace::CanTrace(unsigned level)
{
  return level <= PTraceInfo::Instance().thresholdLevel;
}


ostream & PTrace::Begin(unsigned level, const char * fileName, int lineNum)
{
  PTraceInfo & info = PTraceInfo::Instance();

  if (level == UINT_MAX)
    return *info.stream;

  info.Lock();

  if ((info.filename != NULL) && (info.options&RotateDaily) != 0) {
    unsigned day = PTime().GetDayOfYear();
    if (day != info.lastDayOfYear) {
      info.OpenTraceFile(NULL);
      info.lastDayOfYear = day;
      if (info.stream == NULL)
        info.SetStream(&cerr);
    }
  }

  PThread * thread = PThread::Current();

  if (thread != NULL)
    thread->traceStreams.Push(new PStringStream);

  ostream & stream = thread != NULL ? (ostream &)thread->traceStreams.Top() : *info.stream;

  info.oldStreamFlags = stream.flags();
  info.oldPrecision = stream.precision();

  // Before we do new trace, make sure we clear any errors on the stream
  stream.clear();

  if ((info.options&SystemLogStream) == 0) {
    if ((info.options&DateAndTime) != 0) {
      PTime now;
      stream << now.AsString("yyyy/MM/dd hh:mm:ss.uuu\t", (info.options&GMTTime) ? PTime::GMT : PTime::Local);
    }

    if ((info.options&Timestamp) != 0)
      stream << setprecision(3) << setw(10) << (PTimer::Tick()-info.startTick) << '\t';

    if ((info.options&Thread) != 0) {
      if (thread == NULL)
        stream << "ThreadID=0x"
               << setfill('0') << hex << setw(8)
               << PThread::GetCurrentThreadId()
               << setfill(' ') << dec;
      else {
        PString name = thread->GetThreadName();
        if (name.GetLength() <= 23)
          stream << setw(23) << name;
        else
          stream << name.Left(10) << "..." << name.Right(10);
      }
      stream << '\t';
    }

    if ((info.options&ThreadAddress) != 0)
      stream << hex << setfill('0')
             << setw(7) << (void *)PThread::Current()
             << dec << setfill(' ') << '\t';
  }

  if ((info.options&TraceLevel) != 0)
    stream << level << '\t';

  if ((info.options&FileAndLine) != 0 && fileName != NULL) {
    const char * file = strrchr(fileName, '/');
    if (file != NULL)
      file++;
    else {
      file = strrchr(fileName, '\\');
      if (file != NULL)
        file++;
      else
        file = fileName;
    }

    stream << setw(16) << file << '(' << lineNum << ")\t";
  }

  // Save log level for this message so End() function can use. This is
  // protected by the PTraceMutex or is thread local
  if (thread == NULL)
    info.currentLevel = level;
  else {
    thread->traceLevel = level;
    info.Unlock();
  }

  return stream;
}


ostream & PTrace::End(ostream & paramStream)
{
  PTraceInfo & info = PTraceInfo::Instance();

  paramStream.flags(info.oldStreamFlags);
  paramStream.precision(info.oldPrecision);

  PThread * thread = PThread::Current();

  if (thread != NULL) {
    PStringStream * stackStream = thread->traceStreams.Pop();
    PAssert(&paramStream == stackStream, PLogicError);
    info.Lock();
    *info.stream << *stackStream;
    delete stackStream;
  }
  else {
    PAssert(&paramStream == info.stream, PLogicError);
  }

  if ((info.options&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.
    info.stream->width((thread != NULL ? thread->traceLevel : info.currentLevel) + 1);
    info.stream->flush();
  }
  else
    *info.stream << endl;

  info.Unlock();
  return paramStream;
}


PTrace::Block::Block(const char * fileName, int lineNum, const char * traceName)
{
  file = fileName;
  line = lineNum;
  name = traceName;

  if ((PTraceInfo::Instance().options&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 ((PTraceInfo::Instance().options&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;
  }
}

#endif // PTRACING


///////////////////////////////////////////////////////////////////////////////
// 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();
}

⌨️ 快捷键说明

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