C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

C++빌더 Q&A
C++Builder Programming Q&A
[75848] Re:Re:C++20 CoRoutine 테크닉
김시환 [godson2] 1217 읽음    2020-05-11 09:19
답변 감사드립니다.
결국 빌더에서는 구현이 불가능 하다는 말씀이네요. 타이머를 써야하나 생각했었는데 사실 그것도 생각해보니  이번 상황과 별반 다르지 않더라고요..

결국 무한 반복 부분을 쓰레드를 사용해서 구현해야 할 듯한데 그렇게 되면 기존에 프로그램을 너무 많이 뜻어 고쳐야 해서 어떻게 방법이 없나 고민이었는데 참 힘들게 되었습니다.

개발툴만 만드는 회사가 이것저것 잡다하게 만드는 MS 에 따라 잡히는 것도 모자라 이제 한참 뒤쳐지고 있다는 것이 참 서글픕니다.



빌더(TWx) 님이 쓰신 글 :
: : ==========================
: : 빌더(TWx) 님이 쓰신 글 :
: : : 김시환 님이 쓰신 글 :
: : : : 이 방법은 저도 해 봤는데 안됩니다.
: : : : 프로세스 자체가 이 무한 루프에 갇혀 있는 형국이라 무한 루프를 나가기 전에는 응답을 못하네요..
: : : :
: : : : 물론 메인 폼에 변수를 하나 설정하고 TCP Server에서 응답을 하면서 변수만 바꿔 주고 메인 폼에 타이머 같은거 하나 두어서 주기적으로 해당 변수를 체크하고 있다가 LOOP 함수 동작에 대해 처리하면 동작은 되겠지만 아무래도 뭔가 찝찝한 코딩처럼 느껴져서 문의를 드립니다.
: : : :
: : : : 방법이 정 없다면 어쩔수 없이 사용해야 겠지만 뭔가 좋은 방법이 있으면 좋겠습니다.
: : : : 
: : : :
: : : : 정성훈.해미 님이 쓰신 글 :
: : : : : 루프안에 Application->ProcessMessage() 를 사용해서 처리하는 것이
: : : : : 제일 간단한 방법일 것 같습니다.
: : : : :
: : : : : void __fastcall TForm1::LOOP()
: : : : : {
: : : : :     while(true)
: : : : :     {
: : : : :        if(m_UserStop == true) break ;
: : : : :        Sleep(100) ;
: : : : :        Application->ProcessMessage(); // 추가
: : : : :     }
: : : : : }
: : : : :
: : : : : 김시환 님이 쓰신 글 :
: : : : : : Indy TCP Server 를 사용하여 프로그램을 하고 있습니다.
: : : : : : 외부 클라이언트에서 특정한 동작 요청이 있을 경우 서버 프로그램은 무한 루프 함수를 실행하게 됩니다.
: : : : : :
: : : : : : 그런데 이렇게 될 경우 이 서버가 다른 클라이언트 요청은 정상적으로 수행하는데 이 무한루프 함수를 요청한 클라이언트의 다른 요청은 이 무한루프를 빠져 나가기 전에는 수행을 못합니다.
: : : : : :
: : : : : : 아래 코드의 상황 입니다.
: : : : : :
: : : : : : void __fastcall TForm1::TCPServerExecute(TIdContext *AContext)
: : : : : : {
: : : : : :     TIdBytes ABuffer;
: : : : : :     AContext->Connection->IOHandler->ReadBytes(ABuffer, -1, false);
: : : : : :     int action = Parsing(ABuffer) ;
: : : : : :
: : : : : :     if( action == 1) LOOP() ;
: : : : : : }
: : : : : :
: : : : : : void __fastcall TForm1::LOOP()
: : : : : : {
: : : : : :     while(true)
: : : : : :     {
: : : : : :        if(m_UserStop == true) break ;
: : : : : :        Sleep(100) ;
: : : : : :     }
: : : : : : }
: : : : : :
: : : : : : 결국 클라이언트의 요청이 완전히 동작 완료하기 전에는 동일한 클라이언트의 다른 요청에는 응답을 하지 못한다는 의미인데 이런경우 어떻게 해결하는 것이 좋을까요??
: : : : : : Callback 같은 걸로 해결하는 방법이 있을까요?
: : :
: : :
: : :
: : :
: : :
: : : 답변:
: : :
: : :
: : :
: : : 델파이도 C++ 빌더도 어설프게 알고 있는 사람들이...
: : : ProcessMessage()를 마치 무슨 만능이라도 되는 것 처럼 잘못 사용하고 있는 것 같은데요.
: : :
: : : 예를 들어...
: : :
: : : 리스트 박스에 대량의 데이타를 추가한 다고 할 때...
: : : 리스트 박스 데이타 추가 동작이 일어 날 때 마다 리스트 박스 메세지가 디스페치 돼야 하는데
: : : 싱글 쓰레드로 밖에 동작하지 못하는 VCL 라이브러리의 한계로 인해서
: : : 메인 쓰레드 UI가 얼어 버리는 문제를 피해가기 위한 꼼수로 사용하는 방법이
: : : ProcessMessage()를 이용하는 거고...
: : :
: : : 이 함수는 윈도우 메세지 들을 디스패치 하는 역할 밖에 하지 않습니다.
: : :
: : :
: : :
: : : 질문에 언급되어 있는 근본적인 문제를 해결하기 위해선 CoRoutine 이라는
: : : 테크닉을 이용해야 하는데, C++ Builder 10.4 버전이 나온다고 하더라도
: : : 엠바 컴파일러로는 적용할 수 없을 겁니다.
: : :
: : : 10.4 버전이 나와봤자 컴파일러는 C++17 그대로고, 런타임 라이브러리 버그만 패치 하는 수준에 그칠 것이므로.
: : :
: : : CoRoutine 테크닉은 VC++ 컴파일러 같은 C++20을 지원하는 컴파일러를 사용해야 하고
: : : 비선점 방식으로 서브루틴 Yield를 가능하게 해주므로 질문에 언급되어 있는 근본적인 문제를
: : : 해결할 수 있지요.
: : :
: : :
:
:
:
: 답변:
:
:
: 이전에 올린 답변에 이어
: 간단하게 CoRoutine 테크닉을 이용하는 예제를 만들어서 설명해 보죠.
:
:
: Foo()
: {
:    while(1)
:    {
:        .....
:        SomeWork();
:    }
: }
:
:
: 위와 같이 무한 루프로 돌아가는 함수가 있다고 합시다.
:
:
: 기존의 패러다임으로는 위 함수가 빠져 나오기 전 까지는 루프에 갇혀 있으므로
: 다른 작업을 처리할 수 없죠.
:
:
: 그러나 C++20 CoRoution 테크닉을 이용해서
: Foo() 함수를 다음과 같이 co_yield 키워드를 사용해서 CoRoutine 함수로 정의하면...
:
:
: #include <iostream>
: #include <experimental/coroutine>
: #include <experimental/generator>
:
: using namespace std;
:
: experimental::generator<int> Foo()
: {
:   int i = 0;
:   while (1)
:   {
:     ++i;
:     cout << "Foo()\n";
:     co_yield i;
:   }
: }
:
: void Ex()
: {
:   for (const auto& e : Foo())
:   {
:     cout << "Ex() " << e << endl;
:   }
: }
:
:
: 여기서는 이해하기 쉽게 최소한의 코드를 이용해서 i 값을 증가 시키는 ++i 인스트럭션을
: 네트웍으로 부터 무한대로 데이타를 받는 함수를 대체한다고 해 봅시다.
:
: 위와 같이 Foo() 함수를 CoRoutine 함수로 작성하면...
: while(1)로 무한루프가 걸려있음에도 불구하고
:
:     cout << "Foo()\n";
:
: 와
:
:     cout << "Ex() " << e << endl;
:
: 두 구문이 동시성을 갖고 계속해서 출력되게 됩니다.
: 즉,i 값을 증가 시키면서 Foo()와 Ex() 두개의 함수가 동시에 실행 됨.
:
:
: 마치 쓰레드 처럼 돌아가는 거로 보여서 혼동할 수도 있으나
: CoRoutine은 쓰레드를 이용한 병행성이 아닌, 비선점 방식의 동시성을 갖고 동작하므로
: 쓰레드를 이용한 Callback도 필요 없고, 쓰레드가 아닌 비선점 방식이라 쓰레드 동기화를 위한
: Lock()도 필요 없게 되지요.
:
: 파스칼 언어로 구현되어 있는 Indy 컴포넌트는 이런 구조 자체가 원천적으로 불가능.
:
: while(1) 루프에 걸려있으나 co_yield로 인해 CoRoutine 함수가 서스펜드 상태로 들어가고
: 다시 그 위치 부터 동시성을 갖고 Resume 이 되도록 컴파일러에 의해서 동작하기 때문에
:
:
: 네트웍 프로그램 짤 때...
:
:
: 복잡하게 NonBlocking 모드로 소켓 프로그래밍 할 필요도 없고,
: 쓰레드 생성해서 Callback을 사용할 필요 없이..
:
: 프로그램 로직을 동시성을 갖는 NonBlocking 모드처럼 동작하도록 네트웍 프로그램을
: 간단하고 효율적으로 구현할 수 있는 막강한 파워를 발휘할 수 있게 되죠.
:
: C++20에서 CoRoutine 테크닉은 비선점 Stackless 방식으로 구현되기 때문에
: Full Context Switching 런타임 비용이 필요한 쓰레드를 이용하는 방법 보다
: 훨씬 가볍게 Lightweight로 동시성을 갖도록 처리할 수 있지요.
:
: CoRoutine 테크닉도 깊이있게 들어가려면 A4 용지 수십장은 작성해야 할 것 같아서
: 기술적인 부분은 따로 설명하지 않겠습니다.
:
:
: CoRoutine 테크닉을 이용하려면...
: VC++ 처럼 C++20을 지원하는 컴파일러를 사용해야 함.
:
:
:
:

+ -

관련 글 리스트
75838 Indy TCP Server 에서 무한 루프를 동작 함수를 호출하는 경우... 김시환 1295 2020/04/24
75851     Re:Indy TCP Server 에서 무한 루프를 동작 함수를 호출하는 경우... 처음과같이 1229 2020/05/13
75839     Re:Indy TCP Server 에서 무한 루프를 동작 함수를 호출하는 경우... 정성훈.해미 1189 2020/04/24
75841         Re:Re:Indy TCP Server 에서 무한 루프를 동작 함수를 호출하는 경우... 김시환 1183 2020/04/24
75845             Re:Re:Re:Indy TCP Server 에서 무한 루프를 동작 함수를 호출하는 경우... 빌더(TWx) 1259 2020/05/08
75846                 Re:Re:Re:Re:Indy TCP Server 에서 무한 루프를 동작 함수를 호출하는 경우... 금목암 1072 2020/05/10
75849                     Re:Re:Re:Re:Re:Indy TCP Server 에서 무한 루프를 동작 함수를 호출하는 경우... 김시환 1122 2020/05/11
75847                     Re:C++20 CoRoutine 테크닉 빌더(TWx) 1443 2020/05/10
75848                         Re:Re:C++20 CoRoutine 테크닉 김시환 1217 2020/05/11
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.