One-Time 초기화 사용

다음 예제에서는 일회성 초기화 함수를 사용하는 방법을 보여 줍니다.

동기 예제

이 예제 g_InitOnce 에서 전역 변수는 일회성 초기화 구조입니다. INIT_ONCE_STATIC_INIT 사용하여 정적으로 초기화됩니다.

함수는 OpenEventHandleSync 한 번만 만든 이벤트에 대한 핸들을 반환합니다. InitOnceExecuteOnce 함수를 호출하여 콜백 함수에 InitHandleFunction 포함된 초기화 코드를 실행합니다. 콜백 함수가 성공 OpenEventHandleSync 하면 lpContext에서 반환된 이벤트 핸들을 반환하고, 그렇지 않으면 INVALID_HANDLE_VALUE 반환합니다.

함수는 InitHandleFunction일회성 초기화 콜백 함수입니다. InitHandleFunction 는 CreateEvent 함수를 호출하여 이벤트를 만들고 lpContext 매개 변수에 이벤트 핸들을 반환합니다.

#define _WIN32_WINNT 0x0600
#include <windows.h>

// Global variable for one-time initialization structure
INIT_ONCE g_InitOnce = INIT_ONCE_STATIC_INIT; // Static initialization

// Initialization callback function 
BOOL CALLBACK InitHandleFunction (
    PINIT_ONCE InitOnce,        
    PVOID Parameter,            
    PVOID *lpContext);           

// Returns a handle to an event object that is created only once
HANDLE OpenEventHandleSync()
{
  PVOID lpContext;
  BOOL  bStatus;
  
  // Execute the initialization callback function 
  bStatus = InitOnceExecuteOnce(&g_InitOnce,          // One-time initialization structure
                                InitHandleFunction,   // Pointer to initialization callback function
                                NULL,                 // Optional parameter to callback function (not used)
                                &lpContext);          // Receives pointer to event object stored in g_InitOnce

  // InitOnceExecuteOnce function succeeded. Return event object.
  if (bStatus)
  {
    return (HANDLE)lpContext;
  }
  else
  {
    return (INVALID_HANDLE_VALUE);
  }
}

// Initialization callback function that creates the event object 
BOOL CALLBACK InitHandleFunction (
    PINIT_ONCE InitOnce,        // Pointer to one-time initialization structure        
    PVOID Parameter,            // Optional parameter passed by InitOnceExecuteOnce            
    PVOID *lpContext)           // Receives pointer to event object           
{
  HANDLE hEvent;

  // Create event object
  hEvent = CreateEvent(NULL,    // Default security descriptor
                       TRUE,    // Manual-reset event object
                       TRUE,    // Initial state of object is signaled 
                       NULL);   // Object is unnamed

  // Event object creation failed.
  if (NULL == hEvent)
  {
    return FALSE;
  }
  // Event object creation succeeded.
  else
  {
    *lpContext = hEvent;
    return TRUE;
  }
}

비동기 예제

이 예제 g_InitOnce 에서 전역 변수는 일회성 초기화 구조입니다. INIT_ONCE_STATIC_INIT 사용하여 정적으로 초기화됩니다.

함수는 OpenEventHandleAsync 한 번만 만든 이벤트에 대한 핸들을 반환합니다. OpenEventHandleAsync 는 InitOnceBeginInitialize 함수를 호출하여 초기화 상태로 들어갑니다.

호출이 성공하면 코드는 fPending 매개 변수의 값을 확인하여 이벤트를 만들 것인지 아니면 다른 스레드에서 만든 이벤트에 대한 핸들을 반환할지 여부를 결정합니다. fPendingFALSE이면 초기화가 이미 완료되었으므로 OpenEventHandleAsynclpContext 매개 변수에 반환된 이벤트 핸들을 반환합니다. 그렇지 않으면 CreateEvent 함수를 호출하여 이벤트를 만들고 InitOnceComplete 함수를 호출하여 초기화를 완료합니다.

InitOnceComplete에 대한 호출이 OpenEventHandleAsync 성공하면 는 새 이벤트 핸들을 반환합니다. 그렇지 않으면 이벤트 핸들을 닫고 INIT_ONCE_CHECK_ONLY사용하여 InitOnceBeginInitialize를 호출하여 초기화가 실패했는지 아니면 다른 스레드에서 완료되었는지 확인합니다.

초기화가 다른 스레드 OpenEventHandleAsync 에 의해 완료된 경우 lpContext에서 반환된 이벤트 핸들을 반환합니다. 그렇지 않으면 INVALID_HANDLE_VALUE 반환합니다.

#define _WIN32_WINNT 0x0600
#include <windows.h>

// Global variable for one-time initialization structure
INIT_ONCE g_InitOnce = INIT_ONCE_STATIC_INIT; // Static initialization

// Returns a handle to an event object that is created only once
HANDLE OpenEventHandleAsync()
{
  PVOID  lpContext;
  BOOL   fStatus;
  BOOL   fPending;
  HANDLE hEvent;
  
  // Begin one-time initialization
  fStatus = InitOnceBeginInitialize(&g_InitOnce,       // Pointer to one-time initialization structure
                                    INIT_ONCE_ASYNC,   // Asynchronous one-time initialization
                                    &fPending,         // Receives initialization status
                                    &lpContext);       // Receives pointer to data in g_InitOnce  

  // InitOnceBeginInitialize function failed.
  if (!fStatus)
  {
    return (INVALID_HANDLE_VALUE);
  }

  // Initialization has already completed and lpContext contains event object.
  if (!fPending)
  {
    return (HANDLE)lpContext;
  }

  // Create event object for one-time initialization.
  hEvent = CreateEvent(NULL,    // Default security descriptor
                       TRUE,    // Manual-reset event object
                       TRUE,    // Initial state of object is signaled 
                       NULL);   // Object is unnamed

  // Event object creation failed.
  if (NULL == hEvent)
  {
    return (INVALID_HANDLE_VALUE);
  }

  // Complete one-time initialization.
  fStatus = InitOnceComplete(&g_InitOnce,             // Pointer to one-time initialization structure
                             INIT_ONCE_ASYNC,         // Asynchronous initialization
                             (PVOID)hEvent);          // Pointer to event object to be stored in g_InitOnce

  // InitOnceComplete function succeeded. Return event object.
  if (fStatus)
  {
    return hEvent;
  }
  
  // Initialization has already completed. Free the local event.
  CloseHandle(hEvent);


  // Retrieve the final context data.
  fStatus = InitOnceBeginInitialize(&g_InitOnce,            // Pointer to one-time initialization structure
                                    INIT_ONCE_CHECK_ONLY,   // Check whether initialization is complete
                                    &fPending,              // Receives initialization status
                                    &lpContext);            // Receives pointer to event object in g_InitOnce
  
  // Initialization is complete. Return handle.
  if (fStatus && !fPending)
  {
    return (HANDLE)lpContext;
  }
  else
  {
    return INVALID_HANDLE_VALUE;
  }
}

일회성 초기화