프로카데미 수업

BOOL WaitOnAddress(
  volatile VOID *Address,
  PVOID         CompareAddress,
  SIZE_T        AddressSize,
  DWORD         dwMilliseconds
);

어떤변수의 주소값을 기다리고, 해당 주소값이 변경되는경우 깨어난다.

아직 작동원리를 파악하지못했으며, 얘로인해 동기화 객체에 대한 개념이 윈도우 내부에서 완전히바뀌었다.

동기화객체쪽은 ms에서도 성능을 높이기위해 개량작업을 계속해서 하기때문에, 자주바뀐다.

대표적으로 CriticalSection이 윈도우7에서 윈도우10 Core 으로 넘어오면서 완전히 바뀌었다.

최근에 나온 API로, 지정된 주소의 값이 변경될때까지 기다린다.

실제적인 작동방식이 공개된게 없다. (2021~2 당시 공개되지 않았으나 현재는 공개됨)

개인 실습

#include <windows.h>
#include <synchapi.h>
#include <process.h>
#include <iostream>

#pragma comment(lib, "Kernel32.lib")

volatile LONG value = 0;

unsigned __stdcall Worker(void* arg) 
{
    std::cout << "Worker: 대기 시작" << std::endl;
    LONG expected = 0;
    // 1. value가 0일 때 대기, 값이 바뀌면 깨어남
    WaitOnAddress(&value, &expected, sizeof(value), INFINITE);
    
    // 4. 대기중인 스레드 깨어남!
    std::cout << "Worker: 깨어남! value = " << value << std::endl;
    return 0;
}

int main() 
{
    _beginthreadex(NULL, 0, Worker, NULL, 0, NULL);

    Sleep(2000); // 2. 2초 후 value 변경
    value = 1;
    WakeByAddressSingle(&value); // 3. 대기 중인 스레드 깨우기

    Sleep(1000); // 메인 스레드 종료 대기
    return 0;
}

값을 바꾸면 자동으로 깨어나는게 아니라, WakeByAddressSingle또는 WakeByAddressAll을 호출해줘야 대기중인 스레드가 개어난다. 아래는 비슷한 Event예제.. Event오브젝트로도 충분히 대체가 가능해보이는데? 왜 굳이 새로운걸 만들었을까

#include <windows.h>
#include <process.h>
#include <iostream>

HANDLE hEvent;

unsigned __stdcall Worker(void* arg)
{
    std::cout << "Worker: 대기 시작" << std::endl;
    // 이벤트가 신호 상태가 될 때까지 대기
    WaitForSingleObject(hEvent, INFINITE);
    std::cout << "Worker: 깨어남!" << std::endl;
    return 0;
}

int main()
{
    // 수동 리셋, 초기 비신호 상태 이벤트 생성
    hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    _beginthreadex(NULL, 0, Worker, NULL, 0, NULL);

    Sleep(2000); // 2초 후 이벤트 신호
    SetEvent(hEvent); // 이벤트를 신호 상태로 만들어 워커 스레드 깨움

    Sleep(1000); // 메인 스레드 종료 대기
    CloseHandle(hEvent);
    return 0;
}

첫소감 : 매우 혁신적인 것처럼 말했었는데… 아직 event랑 무슨차이가 있는지 잘 모르겠음.

WaitOnAddress는 유저 오브젝트라고 한다!

커널오브젝트 vs 유저오브젝트

유저오브젝트 / 커널 오브젝트를 나누는 기준은 유저모드에서 해결이 가능하느냐, 커널모드로의 전환이 필요하느냐에 따라 나뉨.