📄 osutils.cxx
字号:
// check icon file
if (!iconFileName.IsEmpty() && !(iconFileName *= currentInfo.GetIcon()))
return false;
// check all of the commands
return (currentInfo.cmds.GetSize() != 0) && (currentInfo.cmds == cmds);
#else
return true;
#endif
}
bool PProcess::HostSystemURLHandlerInfo::Register()
{
#if _WIN32
if (type.IsEmpty())
return false;
// delete any existing icon name
{
RegistryKey key("HKEY_CLASSES_ROOT\\" + type, RegistryKey::ReadOnly);
key.DeleteKey("DefaultIcon");
}
// set icon file
if (!iconFileName.IsEmpty()) {
RegistryKey key("HKEY_CLASSES_ROOT\\" + type + "\\DefaultIcon", RegistryKey::Create);
key.SetValue("", iconFileName);
}
// delete existing commands
PString keyRoot("HKEY_CLASSES_ROOT\\" + type);
{
RegistryKey key(keyRoot + "\\shell", RegistryKey::ReadOnly);
PString str;
for (PINDEX idx = 0; key.EnumKey(idx, str); ++idx) {
{
RegistryKey key(keyRoot + "\\shell\\" + str, RegistryKey::ReadOnly);
key.DeleteKey("command");
}
{
RegistryKey key(keyRoot + "\\shell", RegistryKey::ReadOnly);
key.DeleteKey(str);
}
}
}
// create new commands
{
RegistryKey key3(keyRoot, RegistryKey::Create);
key3.SetValue("", type & "protocol");
key3.SetValue("URL Protocol", "");
RegistryKey key2(keyRoot + "\\shell", RegistryKey::Create);
for (PINDEX i = 0; i < cmds.GetSize(); ++i) {
RegistryKey key1(keyRoot + "\\shell\\" + cmds.GetKeyAt(i), RegistryKey::Create);
RegistryKey key(keyRoot + "\\shell\\" + cmds.GetKeyAt(i) + "\\command", RegistryKey::Create);
key.SetValue("", cmds.GetDataAt(i));
}
}
#endif
return true;
}
///////////////////////////////////////////////////////////////////////////////
// PThread
void PThread::PrintOn(ostream & strm) const
{
strm << GetThreadName();
}
PString PThread::GetThreadName() const
{
return threadName;
}
#if defined(_DEBUG) && defined(_MSC_VER) && !defined(_WIN32_WCE)
static void SetWinDebugThreadName(const char * threadName, DWORD threadId)
{
struct THREADNAME_INFO
{
DWORD dwType; // must be 0x1000
LPCSTR szName; // pointer to name (in user addr space)
DWORD dwThreadID; // thread ID (-1=caller thread, but seems to set more than one thread's name)
DWORD dwFlags; // reserved for future use, must be zero
} threadInfo = { 0x1000, threadName, threadId, 0 };
__try
{
RaiseException(0x406D1388, 0, sizeof(threadInfo)/sizeof(DWORD), (DWORD *)&threadInfo) ;
// if not running under debugger exception comes back
}
__except(EXCEPTION_CONTINUE_EXECUTION)
{
// just keep on truckin'
}
}
#else
#define SetWinDebugThreadName(p1,p2)
#endif // defined(_DEBUG) && defined(_MSC_VER)
void PThread::SetThreadName(const PString & name)
{
if (name.IsEmpty())
threadName = psprintf("%s:%08x", GetClass(), (INT)this);
else
threadName = psprintf(name, (INT)this);
SetWinDebugThreadName(threadName, threadId);
}
PThread * PThread::Create(const PNotifier & notifier,
INT parameter,
AutoDeleteFlag deletion,
Priority priorityLevel,
const PString & threadName,
PINDEX stackSize)
{
PThread * thread = new PSimpleThread(notifier,
parameter,
deletion,
priorityLevel,
threadName,
stackSize);
if (deletion != AutoDeleteThread)
return thread;
// Do not return a pointer to the thread if it is auto-delete as this
// pointer is extremely dangerous to use, it could be deleted at any moment
// from now on so using the pointer could crash the program.
return NULL;
}
PSimpleThread::PSimpleThread(const PNotifier & notifier,
INT param,
AutoDeleteFlag deletion,
Priority priorityLevel,
const PString & threadName,
PINDEX stackSize)
: PThread(stackSize, deletion, priorityLevel, threadName),
callback(notifier),
parameter(param)
{
Resume();
}
void PSimpleThread::Main()
{
callback(*this, parameter);
}
/////////////////////////////////////////////////////////////////////////////
void PSyncPointAck::Signal()
{
PSyncPoint::Signal();
ack.Wait();
}
void PSyncPointAck::Signal(const PTimeInterval & wait)
{
PSyncPoint::Signal();
ack.Wait(wait);
}
void PSyncPointAck::Acknowledge()
{
ack.Signal();
}
/////////////////////////////////////////////////////////////////////////////
void PCondMutex::WaitCondition()
{
for (;;) {
Wait();
if (Condition())
return;
PMutex::Signal();
OnWait();
syncPoint.Wait();
}
}
void PCondMutex::Signal()
{
if (Condition())
syncPoint.Signal();
PMutex::Signal();
}
void PCondMutex::OnWait()
{
// Do nothing
}
/////////////////////////////////////////////////////////////////////////////
PIntCondMutex::PIntCondMutex(int val, int targ, Operation op)
{
value = val;
target = targ;
operation = op;
}
void PIntCondMutex::PrintOn(ostream & strm) const
{
strm << '(' << value;
switch (operation) {
case LT :
strm << " < ";
case LE :
strm << " <= ";
case GE :
strm << " >= ";
case GT :
strm << " > ";
default:
strm << " == ";
}
strm << target << ')';
}
PBoolean PIntCondMutex::Condition()
{
switch (operation) {
case LT :
return value < target;
case LE :
return value <= target;
case GE :
return value >= target;
case GT :
return value > target;
default :
break;
}
return value == target;
}
PIntCondMutex & PIntCondMutex::operator=(int newval)
{
Wait();
value = newval;
Signal();
return *this;
}
PIntCondMutex & PIntCondMutex::operator++()
{
Wait();
value++;
Signal();
return *this;
}
PIntCondMutex & PIntCondMutex::operator+=(int inc)
{
Wait();
value += inc;
Signal();
return *this;
}
PIntCondMutex & PIntCondMutex::operator--()
{
Wait();
value--;
Signal();
return *this;
}
PIntCondMutex & PIntCondMutex::operator-=(int dec)
{
Wait();
value -= dec;
Signal();
return *this;
}
/////////////////////////////////////////////////////////////////////////////
PReadWriteMutex::PReadWriteMutex()
: readerSemaphore(1, 1),
writerSemaphore(1, 1)
{
readerCount = 0;
writerCount = 0;
}
PReadWriteMutex::Nest * PReadWriteMutex::GetNest() const
{
PWaitAndSignal mutex(nestingMutex);
return nestedThreads.GetAt(POrdinalKey((PINDEX)PThread::GetCurrentThreadId()));
}
void PReadWriteMutex::EndNest()
{
nestingMutex.Wait();
nestedThreads.RemoveAt(POrdinalKey((PINDEX)PThread::GetCurrentThreadId()));
nestingMutex.Signal();
}
PReadWriteMutex::Nest & PReadWriteMutex::StartNest()
{
POrdinalKey threadId = (PINDEX)PThread::GetCurrentThreadId();
nestingMutex.Wait();
Nest * nest = nestedThreads.GetAt(threadId);
if (nest == NULL) {
nest = new Nest;
nestedThreads.SetAt(threadId, nest);
}
nestingMutex.Signal();
return *nest;
}
void PReadWriteMutex::StartRead()
{
// Get the nested thread info structure, create one it it doesn't exist
Nest & nest = StartNest();
// One more nested call to StartRead() by this thread, note this does not
// need to be mutexed as it is always in the context of a single thread.
nest.readerCount++;
// If this is the first call to StartRead() and there has not been a
// previous call to StartWrite() then actually do the text book read only
// lock, otherwise we leave it as just having incremented the reader count.
if (nest.readerCount == 1 && nest.writerCount == 0)
InternalStartRead();
}
void PReadWriteMutex::InternalStartRead()
{
// Text book read only lock
starvationPreventer.Wait();
readerSemaphore.Wait();
readerMutex.Wait();
readerCount++;
if (readerCount == 1)
writerSemaphore.Wait();
readerMutex.Signal();
readerSemaphore.Signal();
starvationPreventer.Signal();
}
void PReadWriteMutex::EndRead()
{
// Get the nested thread info structure for the curent thread
Nest * nest = GetNest();
// If don't have an active read or write lock or there is a write lock but
// the StartRead() was never called, then assert and ignore call.
if (nest == NULL || nest->readerCount == 0) {
PAssertAlways("Unbalanced PReadWriteMutex::EndRead()");
return;
}
// One less nested lock by this thread, note this does not
// need to be mutexed as it is always in the context of a single thread.
nest->readerCount--;
// If this is a nested read or a write lock is present then we don't do the
// real unlock, the decrement is enough.
if (nest->readerCount > 0 || nest->writerCount > 0)
return;
// Do text book read lock
InternalEndRead();
// At this point all read and write locks are gone for this thread so we can
// reclaim the memory.
EndNest();
}
void PReadWriteMutex::InternalEndRead()
{
// Text book read only unlock
readerMutex.Wait();
readerCount--;
if (readerCount == 0)
writerSemaphore.Signal();
readerMutex.Signal();
}
void PReadWriteMutex::StartWrite()
{
// Get the nested thread info structure, create one it it doesn't exist
Nest & nest = StartNest();
// One more nested call to StartWrite() by this thread, note this does not
// need to be mutexed as it is always in the context of a single thread.
nest.writerCount++;
// If is a nested call to StartWrite() then simply return, the writer count
// increment is all we haev to do.
if (nest.writerCount > 1)
return;
// If have a read lock already in this thread then do the "real" unlock code
// but do not change the lock count, calls to EndRead() will now just
// decrement the count instead of doing the unlock (its already done!)
if (nest.readerCount > 0)
InternalEndRead();
// Note in this gap another thread could grab the write lock, thus
// Now do the text book write lock
writerMutex.Wait();
writerCount++;
if (writerCount == 1)
readerSemaphore.Wait();
writerMutex.Signal();
writerSemaphore.Wait();
}
void PReadWriteMutex::EndWrite()
{
// Get the nested thread info structure for the curent thread
Nest * nest = GetNest();
// If don't have an active read or write lock or there is a read lock but
// the StartWrite() was never called, then assert and ignore call.
if (nest == NULL || nest->writerCount == 0) {
PAssertAlways("Unbalanced PReadWriteMutex::EndWrite()");
return;
}
// One less nested lock by this thread, note this does not
// need to be mutexed as it is always in the context of a single thread.
nest->writerCount--;
// If this is a nested write lock then the decrement is enough and we
// don't do the actual write unlock.
if (nest->writerCount > 0)
return;
// Begin text book write unlock
writerSemaphore.Signal();
writerMutex.Wait();
writerCount--;
if (writerCount == 0)
readerSemaphore.Signal();
writerMutex.Signal();
// End of text book write unlock
// Now check to see if there was a read lock present for this thread, if so
// then reacquire the read lock (not changing the count) otherwise clean up the
// memory for the nested thread info structure
if (nest->readerCount > 0)
InternalStartRead();
else
EndNest();
}
/////////////////////////////////////////////////////////////////////////////
PReadWaitAndSignal::PReadWaitAndSignal(const PReadWriteMutex & rw, PBoolean start)
: mutex((PReadWriteMutex &)rw)
{
if (start)
mutex.StartRead();
}
PReadWaitAndSignal::~PReadWaitAndSignal()
{
mutex.EndRead();
}
/////////////////////////////////////////////////////////////////////////////
PWriteWaitAndSignal::PWriteWaitAndSignal(const PReadWriteMutex & rw, PBoolean start)
: mutex((PReadWriteMutex &)rw)
{
if (start)
mutex.StartWrite();
}
PWriteWaitAndSignal::~PWriteWaitAndSignal()
{
mutex.EndWrite();
}
// End Of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -