summaryrefslogblamecommitdiffstats
path: root/source/OSSupport/IsThread.cpp
blob: 45e329a68041a4499cff804b4c1b8aa82133001b (plain) (tree)
1
2
3
4
5
6
7
8
9
 
               





                                                                                                              
                     














































                                                                                                      
                              
                        
                                   


























































                                                                                                                           













                                 

                          




                                                                      
        
                     

                                                                  
                                                                 
                                              
                        
                                                       

                                                                 
                                  


















                                                            

// IsThread.cpp

// Implements the cIsThread class representing an OS-independent wrapper for a class that implements a thread.
// This class will eventually suupersede the old cThread class

#include "Globals.h"

#include "IsThread.h"





// When in MSVC, the debugger provides "thread naming" by catching special exceptions. Interface here:
#if defined(_MSC_VER) && defined(_DEBUG)
//
// Usage: SetThreadName (-1, "MainThread");
//

static void SetThreadName( DWORD dwThreadID, LPCSTR szThreadName)
{
	struct
	{
		DWORD dwType; // must be 0x1000
		LPCSTR szName; // pointer to name (in user addr space)
		DWORD dwThreadID; // thread ID (-1=caller thread)
		DWORD dwFlags; // reserved for future use, must be zero
	} info;
	
	info.dwType = 0x1000;
	info.szName = szThreadName;
	info.dwThreadID = dwThreadID;
	info.dwFlags = 0;

	__try
	{
		RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD), (DWORD *)&info);
	}
	__except(EXCEPTION_CONTINUE_EXECUTION)
	{
	}
}
#endif  // _MSC_VER && _DEBUG





////////////////////////////////////////////////////////////////////////////////
// cIsThread:

cIsThread::cIsThread(const AString & iThreadName) :
	m_ThreadName(iThreadName),
	m_ShouldTerminate(false),
	#ifdef _WIN32
		m_Handle(NULL)
	#else  // _WIN32
		m_HasStarted(false)
	#endif  // else _WIN32
{
}





cIsThread::~cIsThread()
{
	m_ShouldTerminate = true;
	Wait();
}





bool cIsThread::Start(void)
{
	#ifdef _WIN32
		ASSERT(m_Handle == NULL);  // Has already started one thread?
		
		// Create the thread suspended, so that the mHandle variable is valid in the thread procedure
		DWORD ThreadID = 0;
		m_Handle = CreateThread(NULL, 0, thrExecute, this, CREATE_SUSPENDED, &ThreadID);
		if (m_Handle == NULL)
		{
			LOGERROR("ERROR: Could not create thread \"%s\", GLE = %d!", m_ThreadName.c_str(), GetLastError());
			return false;
		}
		ResumeThread(m_Handle);

		#if defined(_DEBUG) && defined(_MSC_VER)
			// Thread naming is available only in MSVC
			if (!m_ThreadName.empty())
			{
				SetThreadName(ThreadID, m_ThreadName.c_str());
			}
		#endif  // _DEBUG and _MSC_VER
		
	#else  // _WIN32
		ASSERT(!m_HasStarted);
		
		if (pthread_create(&m_Handle, NULL, thrExecute, this))
		{
			LOGERROR("ERROR: Could not create thread \"%s\", !", m_ThreadName.c_str());
			return false;
		}
		m_HasStarted = true;
	#endif  // else _WIN32

	return true;
}





void cIsThread::Stop(void)
{
	if (m_Handle == NULL)
	{
		return;
	}
	m_ShouldTerminate = true;
	Wait();
}





bool cIsThread::Wait(void)
{
	if (m_Handle == NULL)
	{
		return true;
	}
	LOGD("Waiting for thread %s to finish", m_ThreadName.c_str());
	
	#ifdef _WIN32
		int res = WaitForSingleObject(m_Handle, INFINITE);
		m_Handle = NULL;
		LOGD("Thread %s finished", m_ThreadName.c_str());
		return (res == WAIT_OBJECT_0);
	#else  // _WIN32
		int res = pthread_join(m_Handle, NULL);
		m_Handle = NULL;
		LOGD("Thread %s finished", m_ThreadName.c_str());
		return (res == 0);
	#endif  // else _WIN32
}





unsigned long cIsThread::GetCurrentID(void)
{
	#ifdef _WIN32
		return (unsigned long) GetCurrentThreadId();
	#else
		return (unsigned long) pthread_self();
	#endif
}