📄 win32thread.cpp
字号:
/* -*-c++-*- OpenThreads library, Copyright (C) 2002 - 2007 The Open Thread Group * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details.*///// Win32Thread.c++// ~~~~~~~~~~~#include <memory>#include <string>#include <iostream>#include <process.h>#include <stdlib.h>#if defined(_MSC_VER) && (_MSC_VER < 1300)#ifdef __SGI_STLusing std::size_t;#endif#elseusing std::size_t;#endif#if defined(_MSC_VER) #pragma warning( disable : 4996 )#endif#include "Win32ThreadPrivateData.h"struct Win32ThreadCanceled{};using namespace OpenThreads;DWORD OpenThreads::cooperativeWait(HANDLE waitHandle, unsigned long timeout){ Thread* current = Thread::CurrentThread(); DWORD dwResult ; if(current) { HANDLE cancelHandle = static_cast<Win32ThreadPrivateData*>(current->getImplementation())->cancelEvent.get(); HANDLE handleSet[2] = {waitHandle, cancelHandle}; dwResult = WaitForMultipleObjects(2,handleSet,FALSE,timeout); if(dwResult == WAIT_OBJECT_0 + 1 ) throw Win32ThreadCanceled(); } else { dwResult = WaitForSingleObject(waitHandle,timeout); } return dwResult;}Win32ThreadPrivateData::TlsHolder Win32ThreadPrivateData::TLS;Win32ThreadPrivateData::~Win32ThreadPrivateData(){}const std::string OPENTHREAD_VERSION_STRING = "OpenThread v1.2preAlpha, WindowThreads (Public Implementation)";//-----------------------------------------------------------------------------// Initialize thread master priority level//Thread::ThreadPriority Thread::s_masterThreadPriority = Thread::THREAD_PRIORITY_DEFAULT;bool Thread::s_isInitialized = false;//-----------------------------------------------------------------------------// Class to support some static methods necessary for pthread's to work// correctly.//namespace OpenThreads { class ThreadPrivateActions { //------------------------------------------------------------------------- // We're friendly to Thread, so it can issue the methods. // friend class Thread; private: //------------------------------------------------------------------------- // Win32Threads standard start routine. // static unsigned int __stdcall StartThread(void *data) { Thread *thread = static_cast<Thread *>(data); Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *>(thread->_prvData); if (thread->_prvData==0) return 0; TlsSetValue(Win32ThreadPrivateData::TLS.ID ,data); //--------------------------------------------------------------------- // Set the proper scheduling priorities // SetThreadSchedulingParams(thread); pd->isRunning = true; // release the thread that created this thread. pd->threadStartedBlock.release(); try{ thread->run(); } catch(Win32ThreadCanceled&) { // thread is canceled do cleanup try { thread->cancelCleanup(); } catch(...) { } } catch(...) { // abnormal termination but must be caught in win32 anyway } pd->isRunning = false; return 0; }; //------------------------------------------------------------------------- // Print information related to thread schduling parameters. // static void PrintThreadSchedulingInfo(Thread *thread) { Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *>(thread->_prvData); std::cout<<"Thread "<< thread <<" priority : "; switch(thread->getSchedulePriority()) { case Thread::THREAD_PRIORITY_MAX: std::cout<<"MAXIMAL"<<std::endl; break; case Thread::THREAD_PRIORITY_HIGH: std::cout<<"HIGH"<<std::endl; break; case Thread::THREAD_PRIORITY_DEFAULT: case Thread::THREAD_PRIORITY_NOMINAL: std::cout<<"NORMAL"<<std::endl; break; case Thread::THREAD_PRIORITY_LOW: std::cout<<"LOW"<<std::endl; break; case Thread::THREAD_PRIORITY_MIN: std::cout<<"MINIMAL"<<std::endl; break; } } //-------------------------------------------------------------------------- // Set thread scheduling parameters. // Note that time-critical priority is ommited : // 1) It's not sensible thing to do // 2) there's no enum for that in Thread interface // Also, on Windows, effective thread priority is : // process priority (manipulated with Get/SetProrityClass) + thread priority (here). // // static int SetThreadSchedulingParams(Thread *thread) { Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *>(thread->_prvData); int prio = THREAD_PRIORITY_NORMAL; switch(thread->getSchedulePriority()) { case Thread::THREAD_PRIORITY_MAX: prio = THREAD_PRIORITY_HIGHEST; break; case Thread::THREAD_PRIORITY_HIGH: prio = THREAD_PRIORITY_ABOVE_NORMAL; break; case Thread::THREAD_PRIORITY_NOMINAL: prio = THREAD_PRIORITY_NORMAL; break; case Thread::THREAD_PRIORITY_LOW: prio = THREAD_PRIORITY_BELOW_NORMAL; break; case Thread::THREAD_PRIORITY_MIN: prio = THREAD_PRIORITY_IDLE; break; } int status = SetThreadPriority( pd->tid.get(), prio); if(getenv("OUTPUT_THREADLIB_SCHEDULING_INFO") != 0) PrintThreadSchedulingInfo(thread); return status!=0; }; };};Thread* Thread::CurrentThread(){ return (Thread* )TlsGetValue(Win32ThreadPrivateData::TLS.ID);};//----------------------------------------------------------------------------//// Description: Set the concurrency level (no-op)//// Use static public//int Thread::SetConcurrency(int) { return -1;};//----------------------------------------------------------------------------//// Description: Get the concurrency level//// Use static public//int Thread::GetConcurrency() { return -1;};//----------------------------------------------------------------------------//// Description: Constructor//// Use: public.//Thread::Thread() { // there's no need for this // if(!s_isInitialized) Init(); Win32ThreadPrivateData *pd = new Win32ThreadPrivateData(); pd->stackSize = 0; pd->isRunning = false; pd->cancelMode = 0; pd->uniqueId = 0; pd->threadPriority = Thread::THREAD_PRIORITY_DEFAULT; pd->threadPolicy = Thread::THREAD_SCHEDULE_DEFAULT; pd->detached = false; pd->cancelEvent.set(CreateEvent(NULL,TRUE,FALSE,NULL)); _prvData = static_cast<void *>(pd);}//----------------------------------------------------------------------------//// Description: Destructor//// Use: public.//Thread::~Thread(){ Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *>(_prvData); if(pd->isRunning) { std::cout<<"Error: Thread "<<this<<" still running in destructor"<<std::endl; pd->cancelMode = 0; cancel(); } delete pd; _prvData = 0;}//-----------------------------------------------------------------------------//// Description: Initialize Threading//// Use: public.//void Thread::Init() {// if(s_isInitialized) return;// s_masterThreadPriority = Thread::THREAD_PRIORITY_DEFAULT; s_isInitialized = true;}//-----------------------------------------------------------------------------//// Description: Get a unique identifier for this thread.//// Use: public//int Thread::getThreadId() { Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData); return pd->uniqueId;}//-----------------------------------------------------------------------------//// Description: Get the thread's process id//// Use: public//size_t Thread::getProcessId() { return (size_t) GetCurrentProcessId();}//-----------------------------------------------------------------------------//// Description: Determine if the thread is running//// Use: public//bool Thread::isRunning() { Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData); return pd->isRunning;}//-----------------------------------------------------------------------------//// Description: Start the thread.//// Use: public//int Thread::start() { Win32ThreadPrivateData *pd = static_cast<Win32ThreadPrivateData *> (_prvData); //------------------------------------------------------------------------- // Prohibit the stack size from being changed. // (bb 5/13/2005) it actually doesn't matter. // 1) usually setStackSize()/start() sequence is serialized. // 2) if not than we're in trouble anyway - nothing is protected // pd->stackSizeLocked = true; unsigned int ID; pd->threadStartedBlock.reset(); pd->tid.set( (void*)_beginthreadex(NULL,pd->stackSize,ThreadPrivateActions::StartThread,static_cast<void *>(this),0,&ID)); pd->uniqueId = (int)ID;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -