[WINAPI] C++ 용 WIN32 Thread 클래스 └ C/C++

MFC없이 Win32 API 만을 이용해 Thread 프로그래밍을 하던 중
자바나 C#의 Thread 클래스처럼 class화 해서 사용할 수 있으면 좋겠다고 생각해서
대충 생각나는대로 디자인을 해봤다
일단 간단한 Thread 프로그래밍에는 그럭저럭 만족스러운 모습을 보여주었다
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#ifndef _BASIC_THREAD_H_
#define _BASIC_THREAD_H_

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

/-========================================================================================================================
** File			: BasicThread.h
** Desc			: 기본적인 Thread Class
** Author		: Jin-Gyu Choi
** Create		: 2013.03.28
** Last Modify	: 2013.03.28
========================================================================================================================*-

class BasicThread
{
protected:
	HANDLE m_hThread;		// Window Thread Handle
	DWORD  m_nThreadID;		// Window Thread ID

private:
	BasicThread( const BasicThread& bt ) {}					// 해당 Thread의 복제를 막는다
	BasicThread& operator = ( const BasicThread& bt ) {}	// 해당 Thread의 복제를 막는다
	
	static DWORD WINAPI StaticThreadStart( LPVOID lpParam )	// 실제 Thread의 시작부분
	{
		BasicThread* pThread = (BasicThread*)lpParam;
		return pThread->Run();
	}

protected:
	virtual DWORD Run(void) = 0;	// Protected로 사용자가 직접 호출하는 것을 막음

public:
	BasicThread() : m_hThread( NULL ), m_nThreadID( 0 )
	{
	}
	
	virtual ~BasicThread()
	{
		if( m_hThread ) CloseHandle( m_hThread );
	}

public:
	//----------------------------------------------------------------
	// public functions
	//----------------------------------------------------------------
	bool Start()	// Thread 시작
	{
		if( m_hThread ) // 이미 Thread가 생성되어 있는 경우
		{
			if( WaitForSingleObject( m_hThread, 0 ) == WAIT_TIMEOUT ) {	// Thread Still Running
				return false;	// Start 거부
			}
			CloseHandle( m_hThread );
		}

		// Thread 생성
		m_hThread = CreateThread(
			NULL,			// default security attributes
			0,				// default stack size
			(LPTHREAD_START_ROUTINE)BasicThread::StaticThreadStart,
			this,			// thread function argument = this class
			0,				// default creation flags
			&m_nThreadID	// receive thread identifier
		);

		if( m_hThread != NULL ) return true;

		return false;
	}
	
	void Stop()	// Thread 강제 종료 - 비추!!
	{
		if( this->IsRunning() )	{
			// 강제 Terminate이므로 정상적인 자원 해제를 기대할 수 없음
			// 공유자원 등을 물고 있을 경우 deadlock 등의 위험이 있을 수 있음
			::TerminateThread( m_hThread, -1 );
		}

		if( m_hThread ){
			CloseHandle( m_hThread );
			m_hThread = NULL;
		}
	}

public:
	//----------------------------------------------------------------
	// inline functions
	//----------------------------------------------------------------

	// Getter
	inline HANDLE GetThreadHandle() { return m_hThread; }
	inline DWORD GetThreadID() { return m_nThreadID; }

	// Status
	inline bool IsRunning() 
	{
		if( m_hThread ){
			DWORD dwExitCode = 0;
			::GetExitCodeThread( m_hThread, &dwExitCode );
			if( dwExitCode == STILL_ACTIVE ) return true;
		}
		return false;
	}

	// Join - Wait For Thread Done
	inline void Join()
	{
		::WaitForSingleObject( m_hThread, INFINITE );
	}

	// Yeild - Yeild Execution to Another Thread
	inline BOOL Yeild()
	{
		return ::SwitchToThread();
	}

	// Sleep - Suspends the execution of the current thread until the time-out interval elapses
	inline void Sleep( DWORD dsMilliiseconds )
	{
		::Sleep( dsMilliiseconds );
	}

	// Suspend - Suspend Thread
	inline DWORD Suspend()
	{
		return ::SuspendThread( m_hThread );
	}

	// Resume - Resume Thread
	inline DWORD Resume()
	{
		return ::ResumeThread( m_hThread );
	}

};

#endif
BasicThread 클래스 그 자체로는 Run이 정의되어 있지 않기 때문에 그대로 사용하는 것은 안되고
실제로 사용하기 위해서는 BasicThread 클래스를 상속받아
Run() 함수를 구현해서 사용하면 된다
대략 사용한다면 이런 느낌???
물론 원한다면 맴버변수, static 변수 모두 사용 가능하다
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <stdio.h>
#include "BasicThread.h"

class TestThread : public BasicThread
{
protected:
	DWORD Run(void)
	{
		printf("Thread %d Start\n", GetThreadID());

		for( int i = 0; i < 5; i++ )
		{
			printf("Thread %d : Count %d\n", GetThreadID(), i);
			this->Sleep( 1000 );
		}

		printf("Thread %d End\n", GetThreadID());

		return 0;
	}
};

int main(void)
{
	TestThread* pThread[5];

	for( int i = 0 ; i < 5; i++ )
	{
		pThread[i] = new TestThread();
		pThread[i]->Start();
	}

	for( int i = 0 ; i < 5; i++ )
	{
		pThread[i]->Join();
		delete pThread[i];
	}

	return 0;
}

덧글

댓글 입력 영역