One-Time初期化の使用

次の例は、1 回限りの初期化関数の使用を示しています。

同期の例

この例では、 g_InitOnce グローバル変数は 1 回限りの初期化構造体です。 INIT_ONCE_STATIC_INITを使用して静的に初期化されます。

関数は OpenEventHandleSync 、1 回だけ作成されたイベントへのハンドルを返します。 InitOnceExecuteOnce 関数を呼び出して、コールバック関数に含まれる初期化コードをInitHandleFunction実行します。 コールバック関数が成功した場合は、 OpenEventHandleSynclpContext で返されたイベント ハンドルを返します。それ以外の場合は、 INVALID_HANDLE_VALUEを返します。

関数は InitHandleFunction1 回限りの初期化コールバック関数です。 InitHandleFunctionCreateEvent 関数を呼び出してイベントを作成し、 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 グローバル変数は 1 回限りの初期化構造体です。 INIT_ONCE_STATIC_INITを使用して静的に初期化されます。

関数は OpenEventHandleAsync 、1 回だけ作成されたイベントへのハンドルを返します。 OpenEventHandleAsync は InitOnceBeginInitialize 関数を呼び出して初期化状態に入ります。

呼び出しが成功した場合、コードは fPending パラメーターの値をチェックして、イベントを作成するか、単に別のスレッドによって作成されたイベントにハンドルを返すかを判断します。 fPendingFALSE の場合、初期化は既に完了しているためOpenEventHandleAsynclpContext パラメーターで返されるイベント ハンドルを返します。 それ以外の場合は、 CreateEvent 関数を呼び出してイベントを作成し、 InitOnceComplete 関数を呼び出して初期化を完了します。

InitOnceComplete の呼び出しが成功すると、OpenEventHandleAsync新しいイベント ハンドルが返されます。 それ以外の場合は、イベント ハンドルを閉じ、初期化が失敗したか、別のスレッドによって完了したかを判断するために、INIT_ONCE_CHECK_ONLYInitOnceBeginInitialize を呼び出します。

初期化が別のスレッドによって完了した場合は、 OpenEventHandleAsynclpContext で返されたイベント ハンドルを返します。 それ以外の場合は、 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;
  }
}

1 回限り初期化