📄 win32.cxx
字号:
if ((osError & PWIN32ErrorFlag) == 0) return psprintf("C runtime error %u", osError); DWORD err = osError & ~PWIN32ErrorFlag; static const struct { DWORD id; const char * msg; } win32_errlist[] = { { ERROR_FILE_NOT_FOUND, "File not found" }, { ERROR_PATH_NOT_FOUND, "Path not found" }, { ERROR_ACCESS_DENIED, "Access denied" }, { ERROR_NOT_ENOUGH_MEMORY, "Not enough memory" }, { ERROR_INVALID_FUNCTION, "Invalid function" }, { WSAEADDRINUSE, "Address in use" }, { WSAENETDOWN, "Network subsystem failed" }, { WSAEISCONN, "Socket is already connected" }, { WSAENETUNREACH, "Network unreachable" }, { WSAEHOSTUNREACH, "Host unreachable" }, { WSAECONNREFUSED, "Connection refused" }, { WSAEINVAL, "Invalid operation" }, { WSAENOTCONN, "Socket not connected" }, { WSAECONNABORTED, "Connection aborted" }, { WSAECONNRESET, "Connection reset" }, { WSAESHUTDOWN, "Connection shutdown" }, { WSAENOTSOCK, "Socket closed or invalid" }, { WSAETIMEDOUT, "Timed out" }, { WSAEMSGSIZE, "Message larger than buffer" }, { WSAEWOULDBLOCK, "Would block" }, { 0x1000000, "High level protocol failure" } }; for (PINDEX i = 0; i < PARRAYSIZE(win32_errlist); i++) if (win32_errlist[i].id == err) return win32_errlist[i].msg; return psprintf("WIN32 error %u", err);}BOOL PChannel::ConvertOSError(int status, Errors & lastError, int & osError){ if (status >= 0) { lastError = NoError; osError = 0; return TRUE; } if (status != -2) osError = errno; else { osError = GetLastError(); switch (osError) { case ERROR_INVALID_HANDLE : case WSAEBADF : osError = EBADF; break; case ERROR_INVALID_PARAMETER : case WSAEINVAL : osError = EINVAL; break; case ERROR_ACCESS_DENIED : case WSAEACCES : osError = EACCES; break; case ERROR_NOT_ENOUGH_MEMORY : osError = ENOMEM; break; case WSAEINTR : osError = EINTR; break; case WSAEMSGSIZE : osError |= PWIN32ErrorFlag; lastError = BufferTooSmall; return FALSE; case WSAEWOULDBLOCK : case WSAETIMEDOUT : osError |= PWIN32ErrorFlag; lastError = Timeout; return FALSE; default : osError |= PWIN32ErrorFlag; } } switch (osError) { case 0 : lastError = NoError; return TRUE; case ENOENT : lastError = NotFound; break; case EEXIST : lastError = FileExists; break; case EACCES : lastError = AccessDenied; break; case ENOMEM : lastError = NoMemory; break; case ENOSPC : lastError = DiskFull; break; case EINVAL : lastError = BadParameter; break; case EBADF : lastError = NotOpen; break; case EAGAIN : lastError = Timeout; break; case EINTR : lastError = Interrupted; break; default : lastError = Miscellaneous; } return FALSE;}///////////////////////////////////////////////////////////////////////////////// PWin32OverlappedPWin32Overlapped::PWin32Overlapped(){ memset(this, 0, sizeof(*this)); hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);}PWin32Overlapped::~PWin32Overlapped(){ if (hEvent != NULL) CloseHandle(hEvent);}void PWin32Overlapped::Reset(){ Offset = OffsetHigh = 0; if (hEvent != NULL) ResetEvent(hEvent);}///////////////////////////////////////////////////////////////////////////////// ThreadsUINT __stdcall PThread::MainFunction(void * threadPtr){ PThread * thread = (PThread *)PAssertNULL(threadPtr); thread->SetThreadName(thread->GetThreadName()); PProcess & process = PProcess::Current();#ifndef _WIN32_WCE AttachThreadInput(thread->threadId, ((PThread&)process).threadId, TRUE); AttachThreadInput(((PThread&)process).threadId, thread->threadId, TRUE);#endif process.activeThreadMutex.Wait(); process.activeThreads.SetAt(thread->threadId, thread); process.activeThreadMutex.Signal(); process.SignalTimerChange();#if defined(_WIN32_DCOM) ::CoInitializeEx(NULL, COINIT_MULTITHREADED);#endif thread->Main();#if defined(_WIN32_DCOM) ::CoUninitialize();#endif return 0;}PThread::PThread(PINDEX stackSize, AutoDeleteFlag deletion, Priority priorityLevel, const PString & name) : threadName(name){ PAssert(stackSize > 0, PInvalidParameter); originalStackSize = stackSize; autoDelete = deletion == AutoDeleteThread;#ifndef _WIN32_WCE threadHandle = (HANDLE)_beginthreadex(NULL, stackSize, MainFunction, this, CREATE_SUSPENDED, &threadId);#else threadHandle = CreateThread(NULL, stackSize, (LPTHREAD_START_ROUTINE)MainFunction, this, CREATE_SUSPENDED, (LPDWORD) &threadId);#endif PAssertOS(threadHandle != NULL); SetPriority(priorityLevel); traceBlockIndentLevel = 0; if (autoDelete) { PProcess & process = PProcess::Current(); process.deleteThreadMutex.Wait(); process.autoDeleteThreads.Append(this); process.deleteThreadMutex.Signal(); }}PThread::~PThread(){ if (originalStackSize <= 0) return; PProcess & process = PProcess::Current(); process.activeThreadMutex.Wait(); process.activeThreads.SetAt(threadId, NULL); process.activeThreadMutex.Signal(); if (!IsTerminated()) Terminate(); if (threadHandle != NULL) CloseHandle(threadHandle);}void PThread::Restart(){ PAssert(IsTerminated(), "Cannot restart running thread");#ifndef _WIN32_WCE threadHandle = (HANDLE)_beginthreadex(NULL, originalStackSize, MainFunction, this, 0, &threadId);#else threadHandle = CreateThread(NULL, originalStackSize, (LPTHREAD_START_ROUTINE) MainFunction, this, 0, (LPDWORD) &threadId);#endif PAssertOS(threadHandle != NULL);}void PThread::Terminate(){ PAssert(originalStackSize > 0, PLogicError); if (Current() == this) ExitThread(0); else TerminateThread(threadHandle, 1);}BOOL PThread::IsTerminated() const{ if (this == PThread::Current()) return FALSE; return WaitForTermination(0);}void PThread::WaitForTermination() const{ WaitForTermination(PMaxTimeInterval);}BOOL PThread::WaitForTermination(const PTimeInterval & maxWait) const{ if ((this == PThread::Current()) || threadHandle == NULL) { PTRACE(2, "WaitForTermination short circuited"); return TRUE; } DWORD result; PINDEX retries = 10; while ((result = WaitForSingleObject(threadHandle, maxWait.GetInterval())) != WAIT_TIMEOUT) { if (result == WAIT_OBJECT_0) return TRUE; if (::GetLastError() != ERROR_INVALID_HANDLE) { PAssertAlways(POperatingSystemError); return TRUE; } if (retries == 0) return TRUE; retries--; } return FALSE;}void PThread::Suspend(BOOL susp){ PAssert(!IsTerminated(), "Operation on terminated thread"); if (susp) SuspendThread(threadHandle); else Resume();}void PThread::Resume(){ PAssert(!IsTerminated(), "Operation on terminated thread"); ResumeThread(threadHandle);}BOOL PThread::IsSuspended() const{ SuspendThread(threadHandle); return ResumeThread(threadHandle) > 1;}void PThread::SetAutoDelete(AutoDeleteFlag deletion){ PAssert(deletion != AutoDeleteThread || this != &PProcess::Current(), PLogicError); PProcess & process = PProcess::Current(); if (autoDelete && deletion != AutoDeleteThread) { process.deleteThreadMutex.Wait(); process.autoDeleteThreads.DisallowDeleteObjects(); process.autoDeleteThreads.Remove(this); process.autoDeleteThreads.AllowDeleteObjects(); process.deleteThreadMutex.Signal(); } else if (!autoDelete && deletion == AutoDeleteThread) { process.deleteThreadMutex.Wait(); process.autoDeleteThreads.Append(this); process.deleteThreadMutex.Signal(); } autoDelete = deletion == AutoDeleteThread;}#if !defined(_WIN32_WCE) || (_WIN32_WCE < 300)#define PTHREAD_PRIORITY_LOWEST THREAD_PRIORITY_LOWEST#define PTHREAD_PRIORITY_BELOW_NORMAL THREAD_PRIORITY_BELOW_NORMAL#define PTHREAD_PRIORITY_NORMAL THREAD_PRIORITY_NORMAL#define PTHREAD_PRIORITY_ABOVE_NORMAL THREAD_PRIORITY_ABOVE_NORMAL#define PTHREAD_PRIORITY_HIGHEST THREAD_PRIORITY_HIGHEST#else#define PTHREAD_PRIORITY_LOWEST 243#define PTHREAD_PRIORITY_BELOW_NORMAL 245#define PTHREAD_PRIORITY_NORMAL 247#define PTHREAD_PRIORITY_ABOVE_NORMAL 249#define PTHREAD_PRIORITY_HIGHEST 251#endifvoid PThread::SetPriority(Priority priorityLevel){ PAssert(!IsTerminated(), "Operation on terminated thread"); static int const priorities[NumPriorities] = { PTHREAD_PRIORITY_LOWEST, PTHREAD_PRIORITY_BELOW_NORMAL, PTHREAD_PRIORITY_NORMAL, PTHREAD_PRIORITY_ABOVE_NORMAL, PTHREAD_PRIORITY_HIGHEST }; SetThreadPriority(threadHandle, priorities[priorityLevel]);}PThread::Priority PThread::GetPriority() const{ PAssert(!IsTerminated(), "Operation on terminated thread"); switch (GetThreadPriority(threadHandle)) { case PTHREAD_PRIORITY_LOWEST : return LowestPriority; case PTHREAD_PRIORITY_BELOW_NORMAL : return LowPriority; case PTHREAD_PRIORITY_NORMAL : return NormalPriority; case PTHREAD_PRIORITY_ABOVE_NORMAL : return HighPriority; case PTHREAD_PRIORITY_HIGHEST : return HighestPriority; } PAssertAlways(POperatingSystemError); return LowestPriority;}void PThread::Yield(){ ::Sleep(0);}void PThread::InitialiseProcessThread(){ originalStackSize = 0; autoDelete = FALSE; threadHandle = GetCurrentThread(); threadId = GetCurrentThreadId(); ((PProcess *)this)->activeThreads.DisallowDeleteObjects(); ((PProcess *)this)->activeThreads.SetAt(threadId, this); traceBlockIndentLevel = 0;}PThread * PThread::Current(){ PProcess & process = PProcess::Current(); process.activeThreadMutex.Wait(); PThread * thread = process.activeThreads.GetAt(GetCurrentThreadId()); process.activeThreadMutex.Signal(); return thread;}///////////////////////////////////////////////////////////////////////////////// PProcess::TimerThreadPProcess::HouseKeepingThread::HouseKeepingThread() : PThread(1000, NoAutoDeleteThread, NormalPriority, "PWLib Housekeeper"){ Resume();}void PProcess::HouseKeepingThread::Main(){ PProcess & process = PProcess::Current(); for (;;) { // collect a list of thread handles to check, and clean up // handles for threads that disappeared without telling us process.deleteThreadMutex.Wait(); HANDLE handles[MAXIMUM_WAIT_OBJECTS]; DWORD numHandles = 1; DWORD dwFlags; handles[0] = breakBlock.GetHandle(); for (PINDEX i = 0; i < process.autoDeleteThreads.GetSize(); i++) { PThread & thread = process.autoDeleteThreads[i]; if (thread.IsTerminated()) process.autoDeleteThreads.RemoveAt(i--); else { handles[numHandles] = thread.GetHandle(); // make sure we don't put invalid handles into the list#ifndef _WIN32_WCE if (GetHandleInformation(handles[numHandles], &dwFlags) == 0) { PTRACE(2, "Refused to put invalid handle into wait list"); } else#endif // don't put the handle for the current process in the list if (handles[numHandles] != process.GetHandle()) { numHandles++; if (numHandles >= MAXIMUM_WAIT_OBJECTS) break; } } } process.deleteThreadMutex.Signal(); PTimeInterval nextTimer = process.timers.Process(); DWORD delay; if (nextTimer == PMaxTimeInterval) delay = INFINITE; else if (nextTimer > 1000) delay = 1000; else delay = nextTimer.GetInterval(); DWORD result; int retries = 100; while ((result = WaitForMultipleObjects(numHandles, handles, FALSE, delay)) == WAIT_FAILED) { // if we get an invalid handle error, than assume this is because a thread ended between // creating the handle list and testing it. So, cleanup the list before calling // WaitForMultipleObjects again if (::GetLastError() == ERROR_INVALID_HANDLE) break; // sometimes WaitForMultipleObjects fails. No idea why, so allow some retries else { retries--; if (retries <= 0) break; } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -