Windows, Mac, Linux에서 GCD(Grand Central Dispatch) 사용
개시하다
Mac에서 MacOS X Snow Leopard에 설치된 멀티스레드 프로그래밍 환경인'그랜드 센트럴 디스패치'(이하 GCD)는 애플이 기술을 오픈 소스화할 가치가 있으며, 최근에는 Windows, Linux에 이식하기도 했다.
"XDispatch"바로 그거야.
허가증은 아파치 허가증으로 상당히 두꺼운 상업용 허가증이다.
이 글에서 나는 XDispatch를 사용하고 Windows, Mac, Linux에서 같은 소스 코드를 사용하여 GCD를 이용한 견본을 보여주고 싶다.
그 전에 GCD에 대한 개요, 간단한 강좌는 아래의 글을 참고하십시오.
「 다핵 시대의 새로운 방법!Snow Leopard용 GCD 」(ASCII.jp)
보도를 보면 알 수 있듯이 이것은 매우 우수한 다중 루틴 프로그래밍 환경으로 이전의 다중 루틴 프로그래밍에서 겪었던 어려움과 번거로운 부분을 배제할 수 있다.
하지만 지금까지 가장 큰 병목은'맥에서만 사용할 수 있다'는 것이다.그러나 XDispatch의 등장으로 앞으로 멀티플랫폼에서 GCD를 무심코 이용할 수 있게 됐다.
이를 계기로 GCD가 더 커질 것으로 기대하고 있다.
그럼 상세한 사용 방법을 설명하고 싶습니다.
Notice
설치 및 프로젝트 설치
Window의 경우
Visual Studio 2010이 설치되어 있어야 합니다.
(Visual C++ 2010 Express Edition도 가능)
우선 XDispatch 다운로드 페이지부터'윈도x86'을 클릭하여 다운로드하세요.
다운로드한 zip 파일의 압축을 풀면 다음 폴더로 구성됩니다.
include 폴더의 내용
Visual Studio 프로젝트를 만든 후 프로젝트 속성의 구성 속성 -> VC+ 디렉토리 -> 디렉토리 포함 항목에 include 폴더의 경로를 지정합니다. 폴더 컨텐트마찬가지로 Visual Studio 프로젝트를 제작한 후 프로젝트 속성의'속성 구성'- >'VC+ 디렉터리'- >'라이브러리 디렉터리'프로젝트에서 이lib 폴더의 경로를 미리 지정합니다. 또한 구성 속성 -> 트리거 -> 입력 -> 추가 종속 파일 항목에서 xdispatchD.lib 및 dispatchDlib xdispatch.lib 및 dispatchlib 。(이번에는 QtDispatch.lib, QtDispatchD.lib 필요 없음) bin 폴더 내용이 dll 파일을 실행할 때 필요합니다.이 dll 파일들을 구축된exe 파일과 같은 디렉터리에 넣으십시오.프로젝트를 작성할 때 프로젝트 템플릿에서 Win32 콘솔 응용 프로그램을 선택합니다. Mac의 경우 XCode4.5가 설치되어 있다고 가정합니다. 먼저 XDispatch 다운로드 페이지에서 "Mac OS X-amd64"를 클릭하여 다운로드하십시오. 설치형이기 때문에 설치를 시작합니다. (프로그램 라이브러리는 /Library/framework/xdispatch.framework 및 /Library/frameworks/QtDispatch.framework에 설치됨)프로젝트를 작성할 때 "Command Line Tool"을 선택합니다. 다음 대화상자에서 Type을 C++로 설정합니다.(기타 항목은 적절히...) 프로젝트를 진행할 수 있습니다. 항목을 선택한 다음 대상을 선택하고 다음 화면에서 Framework Search Paths를 /Library/Frameworks로 설정합니다. C++ Standard Library에서 libstdc++(GNUC+standard library)를 선택합니다. Build Phase 탭을 클릭하여 Link Binary With Libraries에 System.framwork 및 xdispatch.frame work를 추가합니다. (+ 버튼을 누르면 대화 상자에 "Add Other..."단추를 누르고 파일 선택 대화상자에서 선택하십시오 /시스템/라이브러리/Frameworks/시스템 시스템framework /라이브러리/Frameworks/xdispatch.framework 탭 )부호화cpp 파일에 다음 코드를 입력하십시오. (다음 코드의 의미:다핵 시대의 새로운 방법!Snow Leopard용 GCD”(ASCII.jp).미안합니다.날치기
#include <dispatch/dispatch.h>
#include <xdispatch/dispatch.h>
#ifdef _WIN32
# include <windows.h>
# include <conio.h>
#endif
int main(int argc, char* argv[])
{
for (int i = 1; i <= 10; ++i)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ${
printf(" %d", i);
});
}
printf("\nDone!\n");
#ifdef _WIN32 // Windows
Sleep(1000);
# ifdef _DEBUG
printf("\nPress Any Key...\n");
_getch();
# endif
#else // Mac, Linux
sleep(1);
#endif
return 0;
}
원래 GCD의 사용에는 블록이라는 C/C++ 언어의 확장 방법이 필요합니다.이것은 소위 벽장과 유사하다이렇게 쓰면 처리 내용을 다른 함수에 넘길 수 있습니다.
다만, Visual C++ 등은 블록을 지원하지 않기 때문에 XDispatch에서
${...}의 쓰기 방법에 따라 매크로에 따라 Visual C++의 경우 C++11의 lambda(ramuda)식으로 대체할 수 있습니다.
따라서 Windows, Mac, Linux의 모든 환경에서 같은 코드를 사용할 수 있도록 ^{} 대신 "{...}"을 써야 한다.또한 Windows 환경에서 C++11의 lambda식을 사용하기 위해C 언어가 아닙니다. 필수입니다.cpp(C++)부터 사용해야 합니다.
실행
실행하기 시작하다.
Done!
1 3 4 5 6 7 8 9 2 10
다 했어!응용편
아까 예에서 디스패치-블록이나 C++11의 λ식을 async에 직접 건네주었지만, 외부에서 변수에 저장된 블록이나 C++11의 λ식을 디스패치에 건네주었다Async한테 어떻게 맡길까요?
실제로 XDispatch에서는 블록과 C+++11의 람다식 모델을 추상화하는 매크로가 준비되지 않았다.
그래서 스스로 손을 써야 한다.
우선, 홍이가 하지 말고 해 보세요.
일단 블락의 경우
void (^hello1)(int) = $(int x)
{
std::cout << "Hello, C++ World! " << x << std::endl;
};
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
${
hello1(1000);
});
다음은 C++11의 λ식이다.잊지 마십시오
#include <functional>
.std::function<void(int)> hello1 = $(int x)
{
std::cout << "Hello, C++ World! " << x << std::endl;
};
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
${
hello1(1000);
});
즉 상술한 변수가 정의한 기술을 매크로화하면 된다는 것이다.이런 느낌인가?
#ifdef _WIN32
# define $func1(type,funcname,arg1) std::function<type(arg1)>funcname
#else
# define $func1(type,funcname,arg1) type(^funcname)(arg1)
#endif
그리고 다음 기술에서 다중 플랫폼의 유니버설 코드를 사용할 수 있다.$func1(void,hello1,int) = $(int x)
{
std::cout << "Hello, C++ World! " << x << std::endl;
};
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
${
hello1(1000);
});
매개 변수가 없는 버전, 매개 변수가 여러 버전인 것을 준비하세요.유감스럽지만 매크로를 정의하는 것 이외에 매개 변수의 수량만 정의할 수 있는 다른 방법은 없습니다.그다지 예쁘지 않다.#ifdef _WIN32
# define $func(type,funcname) std::function<type()>funcname
# define $func1(type,funcname,arg1) std::function<type(arg1)>funcname
# define $func2(type,funcname,arg1,arg2) std::function<type(arg1,arg2)>funcname
...
#else
# define $func(type,funcname) type(^funcname)()
# define $func1(type,funcname,arg1) type(^funcname)(arg1)
# define $func2(type,funcname,arg1,arg2) type(^funcname)(arg1,arg2)
...
#endif
또한 C++11 auto를 사용할 경우 이러한 매크로를 사용하지 않아도 Windows, Mac, Linux를 사용할 수 있습니다auto hello = $(int x)
{
std::cout << "Hello, C++ World! " << x << std::endl;
};
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
${
hello1(1000);
});
이렇게 써도 돼요.그러나 auto는 로컬 변수와 전역 변수에만 사용할 수 있기 때문에 블록과 lamda 공식을 클래스 실례 변수에 대입하려면 상기 매크로를 사용해야 합니다.또는, 템플릿을 사용하는 방법도 있지만, 이렇게 하면 템플릿 지옥에 빠질 수 있기 때문에 추천하지 않습니다^^;
말하자면 이런 일을 하려면 맥과 리눅스의 블록을 포기하고 C++11의 라마식을 쓰면 되지 않겠느냐는 말도 있다.저도 그렇게 생각해요.
그러나 현재 버전의 XDispach,Mac(XCode4.5)에서 std:function은 컴파일을 통해 다음과 같다.
'C++ Standard Library'에서'libc++(LLVMC++ standard library with C++ 11 support)'를 선택하면 XDispach의 헤더 파일에서 (찾지 못하거나 나오거나) 컴파일 오류가 발생하겠지...헤더 파일을 억지로 수정하면 이번 집행 결과가 이상해질 거야...현재 블록과 C+++11의 λ식 거시적 추상화 방법이나 auto를 사용하는 방법은 나무랄 데가 없다. 그러나 앞으로 Visual C++는 Block을 지원하는 것이 가장 좋습니다. libQtDispatch 정보XDispatch 이외에libQtDispatch도 GUI 도구 세트'Qt'와 일치하는 프로그램 라이브러리를 준비한 것 같다(이것에 대해서는 아직 자세한 조사가 안 됐다. 누가 글을 쓸까?).
끝말
어때?Mac, Windows, Linux는 같은 코드의 GCD를 사용할 수 있습니다.
처음에는 썼지만 다중 플랫폼에서 사용할 수 있기 때문에 다중 루틴 프로그래밍 환경으로 GCD를 사용할 때 가장 걱정했던 부분은 해제되었다.
여러분도 GCD를 천천히 사용하세요!
감사의 말
GCD를 개발해 오픈한 애플, XDispatch를 개발한 MLBA팀 여러분께 감사드립니다.
Reference
이 문제에 관하여(Windows, Mac, Linux에서 GCD(Grand Central Dispatch) 사용), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/emadurandal/items/fa6fac306bfebd3ba0de텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)