HANDLE CreateSemaphore( LPSECURITY_ATTRIBUTES Security, LONG InitialCount, LONG MaxCount, LPCTSTR SemaphoreName);
関数の実行が成功すると、セマフォオブジェクトのハンドルが返される。新規セマフォオブジェクトが作成された場合は、GetLastError()の戻り値は0となり、既存のセマフォオブジェクトがオープンされた場合は、GetLastError()の戻り値はERROR_ALREADY_EXISTINGとなる。
名前のないセマフォオブジェクトを作成することも可能である。この場合、そのセマフォオブジェクトへの参照は、ハンドルによってのみ可能となる。名前の無いセマフォオブジェクトは複数作成可能であり、ハンドルによって識別される。
取得したハンドルは、CloseHandleによって解放する。オープンされているハンドルが全てクローズされると、システムは自動的にセマフォオブジェクトを削除する。
セマフォオブジェクトは、内部にカウンタとカウンタの最大数を持つオブジェクトである。カウンタの初期値はInitialCountで、カウンタの最大数はMaxCountで指定される。待機関数を実行するとカウンタが1減少し、ReleaseSemaphore関数を実行するとカウンタが増加する。ただし、カウンタは常に0からMaxCountの間の値を取る。
セマフォオブジェクトの内部カウンタが0のとき、待機関数は再び内部カウンタが1以上になるまで待機する。この機構により、リソースの同時アクセス数の制限などの排他制御が可能となる。
引数の意味は、以下の通り。
| Security | (IN) | セマフォオブジェクトのセキュリティ属性。 |
| InitialCount | (IN) | セマフォオブジェクトの内部カウンタの初期値。 |
| MaxCount | (IN) | セマフォオブジェクトの内部カウンタの最大値。 |
| SemaphoreName | (IN) | セマフォオブジェクトの名前。NULLを指定した場合、名前の無いセマフォオブジェクトが作成される。 |
#define SEMAPHORE_NAME "Test Semaphore Object"
/* アプリケーションを1度に3つまでしか実行できないようにする */
int main()
{
HANDLE hSemaphore;
DWORD result;
/* セマフォオブジェクトの作成/取得 */
hSemaphore = CreateSemaphore(NULL, 3, 3, SEMAPHORE_NAME);
result = WaitForSingleObject(hSemaphore, 0);
/* すでに3つ開いているかどうか判定 */
if(result != WAIT_OBJECT_0) {
printf("既に3つ開いている\n");
} else {
/* 処理 */
printf("処理開始\n");
Sleep(10000);
printf("処理終了\n");
/* 解放 */
ReleaseSemaphore(hSemaphore, 1, NULL);
}
CloseHandle(hSemaphore);
return(0);
}
/* セマフォオブジェクトのハンドル */
HANDLE g_hSemaphore;
/* 1度に3つまでしか実行できないスレッド関数 */
DWORD WINAPI DoThread(DWORD ThreadCount)
{
/* 待機 */
WaitForSingleObject(g_hSemaphore, INFINITE);
/* 処理 */
printf("スレッド%d: 処理開始\n", ThreadCount);
Sleep(1000);
printf("スレッド%d: 処理終了\n", ThreadCount);
/* 後処理 */
ReleaseSemaphore(g_hSemaphore, 1, NULL);
return(0);
}
/* メイン関数 */
int main(int argc, char **argv)
{
HANDLE hThread[5];
int i;
/* セマフォオブジェクトの作成 */
g_hSemaphore = CreateSemaphore(NULL, 3, 3, NULL);
/* スレッドを5つ作成 */
for(i=0; i<5; i++) {
hThread[i] = CreateThread(
NULL, 0, (LPTHREAD_START_ROUTINE)DoThread,
(LPVOID)i, 0, NULL);
Sleep(100);
}
/* スレッドの終了まで待機 */
WaitForMultipleObjects(5, hThread, TRUE, INFINITE);
/* 後処理 */
CloseHandle(g_hSemaphore);
for(i=0; i<5; i++) CloseHandle(hThread[i]);
return(0);
}