Reputation: 2334
UPDATE: I found that the semaphore they are releasing is not the semaphore the monitor thread is waiting! I used cout<<ready
to find the semaphore the threads are releasing is 00000394
, which is not the handle of the semaphore the monitor thread is waiting for. What is the possible reason for this problem? Thank you!
I am new to multithread programming in Windows. Today when I'm writing my online game server, I try to use semaphores in Windows. It is written based on IOCP so that every message is handled in a separate thread. A game consists 4 players.
What I expect it to do is: when receiving a message, a new thread starts and release a ready
. There is a monitor thread waiting for 4 ready
, and then releases 4 all_ready
. Each thread waits one all_ready
and goes on.
The code is here:
CGameHost
is a manager for a 4-player game.
CGameHost::CGameHost(void)
{
init_times=0;
ready = CreateSemaphore(NULL, 0, 4, NULL);
read = CreateSemaphore(NULL, 0, 4, NULL);
all_ready = CreateSemaphore(NULL, 0, 4, NULL);
all_read = CreateSemaphore(NULL, 0, 4, NULL);
monitor_thread = (HANDLE)_beginthreadex(NULL, 0, Monitor, (LPVOID)this, NULL, 0);
}
unsigned __stdcall CGameHost::Monitor( LPVOID p ) // a static function
{
CGameHost *nowp = (CGameHost *)p;
while(true)
{
int i;
for(i=1;i<=MAX_PLAYER;i++)
{
WaitForSingleObject(nowp->ready, INFINITE);//stuck here
cout<<"Get Ready!"<<endl; // This is not outputed, which means it stucks in the last row.
}
for(i=1;i<=MAX_PLAYER;i++)
{
ReleaseSemaphore(nowp->all_ready, 1, NULL);
}
for(i=1; i<=MAX_PLAYER; i++)
{
WaitForSingleObject(nowp->read, INFINITE);
}
for(i=1; i<=MAX_PLAYER;i++)
{
ReleaseSemaphore(nowp->all_read, 1, NULL);
}
}
return 0;
}
void CGameHost::ReleaseReady()
{
ReleaseSemaphore(ready, 1, NULL);
}
void CGameHost::WaitAllReady()
{
WaitForSingleObject(all_ready, INFINITE);
}
void CGameHost::ReleaseRead()
{
ReleaseSemaphore(read, 1, NULL);
}
void CGameHost::WaitAllRead()
{
WaitForSingleObject(all_read, INFINITE);
}
DataProcess::Game
is the message handler for incoming game messages.
CMessage Dataprocess::Game( CMessage* recv_msg )
{
CMessage ret;
int now_roomnum = recv_msg->para1;
int now_playernum = recv_msg->para2;
if(true)
{
cout<<"Received Game Message: "<<endl;
cout<<"type2 = "<<recv_msg->type2;
cout<<" player_num = "<<now_playernum<<" msg= "<<recv_msg->msg<<endl;
}
if(recv_msg->type2 == MSG_GAME_OPERATION)
{
ret.type1 = MSG_GAME;
ret.type2 = MSG_GAME_OPERATION;
cout<<"Entered from "<<now_playernum<<endl;
game_host[now_roomnum].SetMessage(now_playernum, recv_msg->msg);
game_host[now_roomnum].ReleaseReady();
cout<<"Released Ready from "<<now_playernum<<endl;//this is shown
game_host[now_roomnum].WaitAllReady();//stuck here
cout<<"AllReady from"<<now_playernum<<endl;//not shown
}
return ret;
}
Your reply will be of great help for a beginner of Windows multithread programmer like me! Thank you!
Upvotes: 0
Views: 817
Reputation: 2334
Well, I solved it myself. The reason is that I used CreateSemaphore
again after creating the thread, making the player thread visiting different semaphores as the monitor thread... Sorry for my stupidness, and thank you for telling me so much!
Upvotes: 0
Reputation: 2305
If I understood your needs, you should probably have something like this..
HANDLE hPlayersReady[4]; HANDLE hAllPlayed;
Create these 5 events, and then on your monitor thread, do something like this...
while(true)
{
// Wait for all players to move
WaitForMultipleObjects(4, &hPlayersReady, true, INFINITE);
// Process move
...
// Advise players the move was processed...
SetEvent(hAllPlayed);
}
And on your player thread X
while(true)
{
// Make my move
...
// Advise monitor I'm ready
SetEvent(hPlayersReady[X]);
// Wait for ready to do another move
WaitForSingleObject(hAllPlayed);
}
Upvotes: 2