c++ 함수 사용법에 대한 질문

vivisection의 이미지

serial 이나 socket 등 통신프로그램을 만들때 보통 통신담당 thread 를 하나 생성해서 통신담당 thread와 ipc등으로 내부 프로세스와 통신하게 프로그램을 만들었는데, 예전에 어떤사람이 thread가 아닌 함수에서 처리하게 하는걸 본적이 있습니다
리소스 절약할수 있을것 같아 오늘 따라해보려고 노력중인데, 어떻게 로직을 세워야 하는지 도통 감이 안옵니다
대충 어떤식으로 구조를 만들어야 하는지 설명해주시면 감사하겠습니다

jick의 이미지

정확히는 모르겠는데 C++11에서 추가된 이런 것들을 말씀하시는 건가요?

http://en.cppreference.com/w/cpp/thread/async

써본 적은 없지만, 아마도 내부적으로 thread를 써서 동작할 테니 리소스 사용 면에서 별 차이 없지 싶은데요...

twinwings의 이미지

boost::ASIO 말씀하시는 건가요.

쓰레드 기반의 동기식 방식이 아닌 이벤트 기반의 비동기식으로 핸들러 등록해서 사용합니다.

PS. 오해의 소지가 있어 추가합니다. 쓰레드 당연히 사용하지만 소켓당 쓰레드를 할당하지는 않습니다. 1개의 쓰레드는 1개의 이벤트를 처리합니다.

PS2. 제목과 본문이 상이한데 제목을 명확하게 하셔야 글을 많이 읽을 것 같네요.

vivisection의 이미지

vs6 mfc로 만들 프로그램이였습니다
제목이 좀 상이하긴 합니다
말씀하신 이벤트기반의 비동기식이였습니다
근데 쓰레드는 하나도 사용하지 않았습니다
그분이 만든 다른프로그램을 보면 c++ builder 에서도 똑같이 쓰레드는 하나도 사용하지 않고 했었습니다
이렇게도 되는구나 신기했는데, 따라해보려고 하니 어렵습니다

Necromancer의 이미지

하나도 어렵지 않습니다.

주의사항이 있다면 시스템콜이나 C라이브러리에서 역으로 우리가 작성한 코드내의 함수를 호출하는 경우(소위 콜백함수) 이들 함수는 모두 extern C 함수로 처리되어야 하고, 콜백 호출 들어올 경우 해당되는 객체 인스턴스를 찾을 수 있는 매커니즘도 구현해야 합니다. C++은 함수나 메소드 호출시 코드에 쓰지 않아도 내부에서 처리해야 할 객체 인스턴스 정보가 같이 넘나드는데 시스템콜이나 C라이브러리가 호출되면 이 정보가 사라지기 때문에 필요한거고, 보통은 비동기처리를 위한 콜백 세팅시 콜백함수에 들어가는 여분의 void * 등의 인자에 조작해야 할 객체 인스턴스의 포인터를 넘기게끔 만들어 놓는게 일반적입니다. 이것만 주의하면 나머지는 똑같습니다.

단 C++로 만든 라이브러리라면 이 작업 필요 없을수도 있습니다. 대신, 컴파일러와 링커도 사용할 라이브러리 빌드할 때 썼던 버전과 최대한 일치시켜야 합니다. C++ 코드는 컴파일 방식이 컴파일러마다 달라서 심지어 비주얼스튜디오도 버전이 다르면 안되는 경우가 있습니다(C++ DLL 빌드할때 쓴 VS와 그 C++ DLL을 사용하는 프로그램을 빌드하는 VS의 버전 다르면 안돌아가는 경우 꽤 많습니다)

Written By the Black Knight of Destruction

vivisection의 이미지

정답인거 같은데 너무 어렵습니다
언어는 cpp, 컴파일러는 mingw, 라이브러리는 win32api 입니다
콜백함수를 extern c 로 처리해야 한다는건 win32api가 c기반이라서 그런건가요?
socket receive 들어오면 postmessage() 만 날려주면 될거 같은데 socket receive() 함수를 어떤식으로 만들어야 하는지좀 알려주실수 있으시나요?

Necromancer의 이미지

네 C기반이라 그렇습니다. C는 컴파일한 후에도 함수이름이 그대로 남지만, C++은 컴파일하면 함수 이름이 변형(name mangling)되서, C++에서 C코드를 호출하는 경우는 문제 안되는데 C에서 C++ 호출하게 되면 여러 문제가 생깁니다.

win32api면
개별 소켓을 C++에서 SocketClass로 포장했다고 하면

socket() postmessage 쪽에서는

...
SocketClass target=getEventSocket();   // getEventSocket() -> 수신된 소켓의 인스턴스 가져온다 
PostMessage(hWnd,WM_SOCKRECEIVE,(void *)target,NULL);  // WM_SOCKRECEIVE는 임의로 정한 메시지 종류, 인스턴스는 포인터를 void *로 강제 형변환해서 win32api 메시지의 잉여변수인 WPARAM이나 LPARAM에 집어넣는다.
...

postmessage 수신쪽에서는

extern "C" {
  LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
}
 
LRESULT CALLBACK WndProc(HWND w,UINT message,WPARAM wp,LPARAM lp) {
 switch(message) {
  ...
  case WM_SOCKRECEIVE:
   SocketClass *target=(SockClass *)wp;   // 파라미터로 넘어온 객체 인스턴스를 원래 클래스 형으로 복구
   target->receive();                     // 수신시 원하는 작업을 수행할 메소드 호출
   break;
 }
}

win64로 가면 이방법도 안먹히겠군요. WPARAM, LPARAM은 32bit라서 인스턴스 주소를 가져와서 void *로 강제 형변환한 다음 32비트씩 잘라야 할겁니다.

Written By the Black Knight of Destruction

vivisection의 이미지

감사합니다
엄청 큰 도움이 되었습니다

익명 사용자의 이미지

https://en.wikipedia.org/wiki/Reactor_pattern
boost Asio도 reactor pattern을 구현한것입니다.

이번기회에 reactor pattern에 대해서 공부해보세요.
한번 익숙해지시면 큰 도움이 될겁니다.
Kernel부터 DB, server application, Desktop application 등등 event-driven architecture를 구현하는데
안쓰이는곳이 없습니다. 즉, 기본중의 기본인 핵심 패턴중 하나입니다.
http://www.amazon.com/Network-Programming-Volume-Mastering-Complexity/dp/0201604647

위책의 저자인 Douglas교수가 낸 Pattern oriented software architecture Vol.2에 소개된 아주 유명한 패턴입니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.