11장 윈도우 스레드풀
- 비동기 함수 호출(스레드)
- 시간 간격을 두고 함수 호출(타이머)
- 커널 오브젝트가 시그널 되면 함수 호출(이벤트)
- 비동기 I/O 요청 완료되면 함수 호출(IOCP)
12장 파이버
3.
11장 윈도우 스레드풀
- 비동기 함수 호출(스레드)
- 시간 간격을 두고 함수 호출(타이머)
- 커널 오브젝트가 시그널 되면 함수 호출(이벤트)
- 비동기 I/O 요청 완료되면 함수 호출(IOCP)
12장 파이버
4.
윈도우 스레드 풀이란?
스레드 생성, 파괴, 관리작업을 좀 더 쉽게구
현 할 수 있도록 제공(책에서는 비스타 이상)
어렵지 않아요~
5.
비동기 함수 호출(스레드)를뙇!
VOID NTAPI SimpleCallback(
PTP_CALLBACK_INSTANCE 사용자 정의
pInstance,
PVOID pvContext
);
BOOL TrySubmitThreadpoolCallback(
PTP_SIMPLE_CALLBACK pfnCallback,사용자 정의 함수
작업 요청(비동기적으로)
PVOID pvContext,
PTP_CALLBACK_ENVIRON pcbe
);
명시적 작업 항목제어
TrySubmitThreadpoolCallback 실패시
(메모리 부족,메모리 할당제한등..)
8.
명시적 작업 항목제어
스레드 풀에서 작업 항목이 들어 가지
않는다면?
내부적으로 작업 항목을 새로 생성 한 후
작업 항목을 스레드 풀 큐에 넣음
=> 작업 항목 큐를 이용하자!
9.
명시적으로 작업 항목을제어 하려면
1.작업 항목 만들고
2.큐에 넣고
VOID CALLBACK WorkCallback( 0.작업 할 콜백함수 구현
PTP_CALLBACK_INSTANCE Instance,
PVOID Context,
PTP_WORK Work);
PTP_WORK CreateThreadpoolWork(
PTP_WORK_CALLBACK 1.콜백 함수 원형 넣고
pfnWorkHandler, 작업 항목 만듦
PVOID pvContext,
PTP_CALLBACK_ENVIRON pcbe);
VOID SubmitThreadpoolWork(PTP_WORK 2. 큐에 넣기
pWork);
10.
명시적 작업 항목제어
삽입한 장업항목을 취소하거나
처리될때까지 특정 스레드를 대기상태
VOID WaitForThreadpoolWorkCallbacks(
PTP_WORK pWork,
BOOL bCancelPendingCallbacks);
True면 취소,처리중이라면 취소하지 않고 처리될때 까지 대기
False면 완전히 처리 될떄까지 대기
11.
명시적 작업 항목제어
VOID CloseThreadpoolWork(PTP_WORK pwk);
작업 항목이 더 이상 필요 없다면
작업 항목 제거
11장 윈도우 스레드풀
- 비동기 함수 호출(스레드)
- 시간 간격을 두고 함수 호출(타이머)
- 커널 오브젝트가 시그널 되면 함수 호출(이벤트)
- 비동기 I/O 요청 완료되면 함수 호출(IOCP)
12장 파이버
14.
시간 간격을 두고함수 호출(타이머)를 뙇!
VOID CALLBACK TimeoutCallback(
PTP_CALLBACK_INSTANCE pInstance,
PVOID pvContext, 타이머 함수 원형
PTP_TIMER pTimer);
PTP_TIMER CreateThreadpoolTimer(
타이머 생성
PTP_TIMER_CALLBACK
pfnTimerCallback,
PVOID pvContext,
PTP_CALLBACK_ENVIRON pcbe)
VOID SetThreadpoolTimer(
PTP_TIMER pTimer,
PFILETIME pftDueTime, 타이머 스레드 풀에 등록
DWORD msPeriod,
DWORD msWindowLength);
15.
시간 간격을 두고함수 호출
콜백 함수가 정확한 시간에 호출
해주는 것 보다 스레드를 깨웠다가
다시 대기 상태로 만드는 비용을
줄이는 것이 중요
타이머를 한번 만들고 SetThreadpoolTimer()
을 이용해서 시간 조작
16.
시간 간격을 두고함수 호출
VOID SetThreadpoolTimer(
PTP_TIMER pTimer,
PFILETIME pftDueTime,
DWORD msPeriod,
DWORD msWindowLength);
pftDueTime 을 NULL로 넣으면
타이머 호출 X
타이머 오브젝트를 파괴 하지 않고
타이머 정지 가능
17.
시간 간격을 두고함수 호출
삽입한 타이머을 취소하거나
처리될때까지 특정 스레드를 대기상태
VOID WaitForThreadpoolTimerCallbacks(
PTP_WORK pWork,
BOOL bCancelPendingCallbacks);
True면 취소,처리중이라면 취소하지 않고 처리될때 까지 대기
False면 완전히 처리 될떄까지 대기
18.
11장 윈도우 스레드풀
- 비동기 함수 호출(스레드)
- 시간 간격을 두고 함수 호출(타이머)
- 커널 오브젝트가 시그널 되면 함수 호출(이벤트)
- 비동기 I/O 요청 완료되면 함수 호출(IOCP)
12장 파이버
19.
커널 오브젝트가 시그널되면 함수 호출
(이벤트)를 뙇!
VOID CALLBACK WaitCallback(
PTP_CALLBACK_INSTANCE pInstance, 시그널 대기 함수 원형
PVOID Context,
PTP_WAIT Wait,
TP_WAIT_RESULT WaitResult);
PTP_WAIT CreateThreadpoolWait(
PTP_WAIT_CALLBACK pfnWaitCallback, 시그널 대기 함수 생성
PVOID pvContext,
PTP_CALLBACK_ENVIRON pcbe);
VOID SetThreadpoolWait(
PTP_WAIT pWaitItem,
HANDLE hObject, 스레드 풀에 등록
PFILETIME pftTimeout);
20.
커널 오브젝트가 시그널되면 함수 호출
VOID SetThreadpoolWait(
PTP_WAIT pWaitItem,
HANDLE hObject,
PFILETIME pftTimeout);
핸들 오브젝트를 사용
시그널 상태가 됬을 때 콜백 함수를 호출
21.
커널 오브젝트가 시그널되면 함수 호출
내부적으로 스레드 풀은
WaitForMultipleObjects을 이용하기 때문
64개만 대기 가능
동일한 커널 오브젝트를 동시에 여러 번
사용이 안되므로 DuplicateHandle을 이용
복사된 핸들을 각각 등록
22.
커널 오브젝트가 시그널되면 함수 호출
프로세스 커널 오브젝트는 한번 시그널이면
영원히 시그널 상태
SetThreadpoolWait 호출할때 다른 오브젝트
또는 Null값을 전달해서 해당 핸들을 제거
23.
커널 오브젝트가 시그널되면 함수 호출
콜백 함수 내에서 WaitForThreadpoolWork
호출 하면 데드락
SetThreadpoolWait 매개 변수로 전달한
커널 오브젝트는 삭제 하면 안됨!
24.
커널 오브젝트가 시그널되면 함수 호출
대기중인 커널 오브젝트에 대해
PulseEvent 같은 시그널 함수 호출도 안됨!
해당 이벤트가 호출한 시점에 대기 하고
있음을 보장을 못함!
25.
11장 윈도우 스레드풀
- 비동기 함수 호출(스레드)
- 시간 간격을 두고 함수 호출(타이머)
- 커널 오브젝트가 시그널 되면 함수 호출(이벤트)
- 비동기 I/O 요청 완료되면 함수 호출(IOCP)
12장 파이버
26.
비동기 I/O 요청완료되면 함수 호출(IOCP)
뙇!
10장에 대략적으로 다룸
어떤 함수를 호출 할지를 지정하기만
하면 됨
27.
비동기 I/O 요청완료되면 함수 호출(IOCP)
VOID CALLBACK
OverlappedCompletionRoutine(
PTP_CALLBACK_INSTANCE pInstance,
PVOID pvContext,
PVOID pOverlapped, I/O 작업 완료시 호출되는 함수 원형
ULONG IoResult,
ULONG_PTR NumberOfBytesTransferred,
PTP_IO pIo);
스레드 풀 I/O 오브젝트 생성
PTP_IO CreateThreadpoolIo(
HANDLE hDevice, 파일/장치 핸들값을 넣어줌
PTP_WIN32_IO_CALLBACK
pfnIoCallback,
PVOID pvContext,
PTP_CALLBACK_ENVIRON pcbe);
28.
비동기 I/O 요청완료되면 함수 호출(IOCP)
VOID StartThreadpoolIo(PTP_IO pio); I/O 오브젝트와 스레드 풀 연동
단,풀에 넣고 나서 READ/WRITE 할것
VOID CancelThreadpoolIo(PTP_IO pio); I/O 작업이 실패 하면 반드시 호출
VOID CloseThreadpoolIo(PTP_IO pio); 사용을 마치려면 …
I/O 오브젝트 닫기
29.
비동기 I/O 요청완료되면 함수 호출(IOCP)
VOID WaitForThreadpoolIoCallbacks(
PTP_IO pio,
BOOL bCancelPendingCallbacks);
I/O 작업이 완료 될때까지 다른 스레드가 대기 시킴
True 면 시작 되지 않은 모든 요청을 취소
완료 통지도 발생 X
30.
+@ 콜백 종료동작
콜백 함수가 종료 될때 쓰면 유용
LeaveCriticalSectionWhenCallbackReturns
ReleaseMutexWhenCallbackReturns
ReleaseSemaphoreWhenCallbackReturns
SetEventWhenCallbackReturns
FreeLibraryWhenCallbackReturns
스레드 풀이 종료시 자동적으로 호출
31.
스레드 풀 커스터마이징뙇!
스레드 풀에서 동작하는
스레드의 최소 최대 개수를 설정
OR
스레드 풀을 각각 독립적으로 생성,파괴
32.
스레드 풀 커스터마이징
PTP_POOLCreateThreadpool(PVOID reserved);
BOOL SetThreadpoolThreadMinimum(PTP_POOL pThreadPool,
DWORD cthrdMin);
BOOL SetThreadpoolThreadMaximum(PTP_POOL pThreadPool,
DWORD cthrdMost);
VOID CloseThreadpool(PTP_POOL pThreadPool);
기본 스레드 풀은 최소 스레드 1개 최대 500개를 가짐
33.
11장 윈도우 스레드풀
- 비동기 함수 호출(스레드)
- 시간 간격을 두고 함수 호출(타이머)
- 커널 오브젝트가 시그널 되면 함수 호출(이벤트)
- 비동기 I/O 요청 완료되면 함수 호출(IOCP)
12장 파이버
34.
파이버라 쓰고 코루틴이라읽는다…
코루틴은 마치 예전 OS의
비선점형(non-preemptive) 쓰레드와
비슷하게 동작
프로그래머가 강제로 컨텍스트 스위칭
명령을 줘야 스위칭
35.
파이버
기존 UNIX 프로그램을포팅하기 위해서…
윈도우는 그냥 스레드 쓰면 됨….
유저모드에서 돌아서 가볍다
스케줄링을 직접 해야 함
36.
파이버 함수 사용
ConvertThreadToFiber
PVOID ConvertThreadToFiberEx(
PVOID pvParam,
DWORD dwFlags);
기존 스레드를 파이버로 변경
파이버 단위에는 부동소수점 상태 정보를 포함하지 않으므로
플래그에 FIBER_FLAG_FLOAT_SWITCH를 넣어줌
37.
파이버 함수 사용
VOID WINAPI FiberFunc(PVOID pvParam); 파이버 함수 원형
PVOID CreateFiberEx(
SIZE_T dwStackCommitSize,
SIZE_T dwStackReserveSize,
DWORD dwFlags,
PFIBER_START_ROUTINE pStartAddress,
PVOID pvParam);
새로운 파이버를 생성
리턴 받은 컨텍스트 정보를 저장 해두고 사용
38.
파이버 함수 사용
VOIDSwitchToFiber(PVOID pvFiberExecutionContext);
바이퍼 간 스위칭
컨텍스트 정보를 이용해서 스위칭을 함
PVOID GetCurrentFiber(); 현재 컨텍스트 주소를 얻어옴