쓰레드를 사용할때 객체지향적으로 코딩하려면 어떻게 해야하나

bejoy4him의 이미지

윈도 환경에서 VC++가지고 프로그램을 짜다가 쓰레드를 써야할일이 있어서
사용하다보니 객체지향과는 완전 작별을 하더군요.

다른 좋은 방법이 있었겠지만, C++쪽은 완전 초보인지라 그렇게 흘러갈수 밖에 없었습니다.
그렇게 엉망을 만들어놓고 생각해보니 다른 좋은 방법이 있지 않을까하는 생각이 들어서
이곳에 글을 올리게 되었습니다.

그렇게 깔끔하지는 않지만, 멤버 변수들은 왠만하면 protected,private등으로 선언해놓고
필요에 의해 클래스내에 쓰레드를 당연히 만들수 있을것이라고 생각하고 쓰레드를 만들려고 하니
static이 아니면 만들수가 없더군요. 문제는 static으로 만들어버리면 static이 아닌 멤버 변수및
함수에 접근,호출할수가 없을것이라는 생각이 들더군요..

그래서 울며 겨자먹기로 쓰레드를 전역함수로 선언하고나니.. 그 쓰레드에서 객체에 접근할때
public으로 접근할수 밖에 없어 protected,private등으로 선언된 녀석들을 하나씩 public으로
접근지정자를 수정하니, 이게 뭐하는 짓인가 하는 생각이 들더군요.

분명, 다른 길이 있을거라는 생각과 함께 이곳에 글을 올리게 되었네요.
다른 좋은 방법을 알려주시면 감사하겠습니다.

좋은 답변. 미리 감사드립니다.

익명 사용자의 이미지

이 책과
Thinking In C++, Volume 2: Practical Programming
Bruce Eckel, President, MindView, Inc.
Chuck Allison, Utah Valley State College
(특히, 11장 Concurrency...)
음 pdf파일로 책을 구하거나, 링크로 보거나, 하나 사거나....

이 라이브러리면 어떨까요?
http://zthread.sourceforge.net/

myueho의 이미지

thread 함수에 this 포인터를 넘겨주고,
thread 함수에서 받은 포인터로 적절한 함수를 호출해주면 됩니다.

antibug의 이미지

뭐 대략 이런 식이죠...

class MyThread
{
public:
bool Create( ... )
{
HANDLE thread = ::CreateThread( ..., thread_proc, (void *)this, ... ) ;
return thread != NULL ;
}

virtual int Run( void ) = 0 ;

private:
static int thread_proc( void *p )
{
MyThread *pThis = (MyThread*)p ;
return pThis->Run() ;
}
} ;

이것 저것 만들다보면...
쓰레드를 가장 잘 쓰는 방법은 안 쓰는 것이다...
뭐 이런말이 가슴을 후벼팝니다... ㅠ.ㅠ;;
그럼에도 불구하고 쓸수밖에 없는 상황은... ㅠ.ㅠ;;

--------------------------------------
재미없는 일은 하지 말자는 인간 쓰레기.
-.-;

happyjun의 이미지

Test 클래스의 Work()를 쓰레드로 실행할 때 보통은 다음과 같은 방법을 사용합니다.

class Test
{
public:
    void Work();
};

static void* startTestWork( void* testObject )
{
    Test* test = static_cast<Test*>( testObject );
    test->Work();
    return NULL;
}

int main()
{
    Test test;
    pthread_t thread;

    pthread_create( &thread, NULL, startTestWork, &test );
    pthread_join( thread, NULL );
}

boost::thread는 플렛폼 중립적인 라이브러리 입니다. 제가 알기로는 다음 C++ 표준에도 들어가는 것으로 알고 있습니다. 동기화 장치들을 사용할 때는 boost::thread의 boost::mutex::scoped_lock 를 사용하시면 실수로 데드락에 빠지는 것을 막아줍니다.

위의 예제는 다음과 같이 사용할 수 있습니다.

#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
using boost;

class Test
{
public:
    void Work();
};

int main()
{
    Test test;

    thread thrd( bind( &Test::Work, &test ) );
    thrd.join();
}

----------------------------------------
http://moim.at
http://mkhq.co.kr

익명 사용자의 이미지

윈도우 VC에서는 기본적으로 쓰레드를 객체 지향적으로 사용하지 않나요?

API로 쓴다면 모를까 MFC에서는 기본적으로 클래스화 되어 있습니다.
객체 지향=클래스냐고 물으신다면 ?? 그건 논외로 하고..

MFC에서는 쓰레드를 CWinThread 객체로 관리를 합니다.

Worker쓰레드는 함수로 돌아가지만,
그 쓰레드를 CWinThread포인터로 관리하고,

UI쓰레드는 처음부터 CWinThread를 상속받아 돌아가는 클래스 객체입니다.

더욱이 UI쓰레드는 메시지 큐까지 가지고 있어서,
윈도우객체와 매우 비슷하죠.

VC에서의 쓰레드만큼 사용하기 쉬운 것은 잘 못보았는데요.....

kihongss의 이미지

====================================================================================
- thread.h -
====================================================================================
class CThread
{
public:
        CThread();
        virtual ~CThread();
        virtual void Run() = 0;        // 상속받아서 쓸것
        void Begin();                // 쓰레드 시작
        void Join();                // 쓰레드 종료시까지 대기
protected:
        HANDLE m_hThread;        // 쓰레드 핸들

private:
        static unsigned int __stdcall ThreadHandler(void *pParam);
        bool m_bIsStarted;
};

====================================================================================
- thread.cpp
====================================================================================

#include "StdAfx.h"
#include <process.h>
#include ".\thread.h"

CThread::CThread() : m_bIsStarted(false),m_hThread(INVALID_HANDLE_VALUE)
{
}

CThread::~CThread()
{
        // _beginthreadex에 의해 리턴된 쓰레드 핸들은 명시적으로 핸들을 닫아줘야함
        if(m_hThread != INVALID_HANDLE_VALUE)
                CloseHandle(m_hThread);

        m_hThread = INVALID_HANDLE_VALUE;
}

void CThread::Begin(){

        UINT threadID;

        if(m_bIsStarted)
                return;

        // 쓰레드 생성
        m_hThread = (HANDLE) _beginthreadex(NULL,0,ThreadHandler,(void*)this,0,&threadID);

        m_bIsStarted = true;
}

// 쓰레드 핸들러
unsigned int __stdcall CThread::ThreadHandler(void *pParam){

        CThread *thread = (CThread*)pParam;
        thread->Run();

        // 쓰레드 종료값, 쓰레드 object를 signaled state로 변경 --> WaitForSingleObject()류의 함수와 사용
        _endthreadex(0);

        return 0;
}

// 쓰레드가 종료할때까지 대기
void CThread::Join(){

        ::WaitForSingleObject(m_hThread,INFINITE);
        // 핸들 닫기
        CloseHandle(m_hThread);
        m_hThread = INVALID_HANDLE_VALUE;
}

예전에 심심해서(?) 짰던 코드인데 참고바래요~ :D

tinywolf의 이미지

저도 디스트럭터에 5초동안 종료를 기다리고 삭제되도록 넣어놓고 썼었죠.. ㅎㅎ

ㅡ_ㅡ;

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.