Question

I have two threads on my Server, one Worker thread and one Receiving Thread. There is a shared Queue containing list of all active Clients for this Server i.e. Queue has IP and Port Number of each Active Client

Worker Thread is in Critical Section and keeps popping data out of the queue and sends a message to each IP and Port Number popped out.

Receiving Thread only waits for new connections and as soon as a new client in addition to active clients arrives, Receiving Thread immediately wants Worker Thread to leave the Critical section so that Receiving Thread may enter the critical Section and write to the Queue.

How can this be achieved? Is there any way that a thread when calls EnterCriticalSection must immediately force all other threads to leave critical section and gets access to Critical Section (This is some kind of priority I guess).

In my code, Worker Thread is always in Critical Section. When Receive Thread wants to enter Critical Section, it sets an event, Worker Thread checks for this Event and Leaves critical Section. Worker Thread then waits until this event is reset and again gets the access of critical secion.

Is my approach correct? Is there any better way to do this?

   DWORD WINAPI workerThreadProcedure(LPVOID param)
   {
    struct node* sendBuff;
    char sendBuffer[600];
    while(1)
    {
       EnterCriticalSection(&cs);
       Sleep(500);
       if((WaitForSingleObject(data_available_event,0)) == WAIT_OBJECT_0 ) /*check for event*/
       {
         //Event is Set. Leave critical Section now
         LeaveCriticalSection(&cs); 
         while(WaitForSingleObject(data_available_event,0) == WAIT_OBJECT_0)
          {
           //Waiting to get REset \r\n");
          }
        //REset Done
        EnterCriticalSection(&cs); //again enter Critical Section.
       } 
       //Going to pop data out
       sendBuff = pop();
       while(sendBuff != NULL) // while Queue is not empty
       {
         //sendto() some data on socket
         sendBuff = pop();
       }
      LeaveCriticalSection(&cs);
    }
    return 0;
   }
DWORD WINAPI receiveThreadProcedure(LPVOID param)   
{
 //recvfrom()
 // if received Buffer is from a new Client
 SetEvent(data_available_event); /* signal worker thread that data is available and now I want to write to Queue*/
   struct node* cur;
   char clientPort[12], detail[512], *clientIP = inet_ntoa(clientSocket.sin_addr); 
   int cliPort = ntohs(clientSocket.sin_port);
   itoa(cliPort,clientPort,10);
   strcat(clientIP," ");
   strcpy(detail,clientIP);
   strcat(detail,clientPort);
   EnterCriticalSection(&cs);
   cur =cread();
   cur->data = detail;
   cur->n=NULL;
   push(cur);
   ResetEvent(data_available_event);
   LeaveCriticalSection(&cs);
}

EDIT: now, when I run this code, receive Thread Enters critical section when new client comes, push()es some data in and then resets the event after which Worker Thread again enters the critical Section but then I get following error while popping.

Unhandled exception at 0x01031ba5 in Master.exe: 0xC0000005: Access violation reading location 0x00000000.

Was it helpful?

Solution

Your workerThreadProcedure does not have to stay in the critical section all the time! See the position in your code where your have the Sleep(500): Sleeping 500 ms within the critical section is useless.

Instead:

while(1)
{
   LeaveCriticalSection(&cs);
   Sleep(500);
   EnterCriticalSection(&cs);
   .
   .

This will release the critical section while the workerThreadProcedure isn't doing anything and your receiveThreadProcedure can aquire the critical section.

Note 1:

if((WaitForSingleObject(data_available_event,0)) == WAIT_OBJECT_0 ) 

has no else handling. WaitForSingleObject may return with a result different from WAIT_OBJECT_0.

Note 2:

while(WaitForSingleObject(data_available_event,0) == WAIT_OBJECT_0)
{
   //Waiting to get REset \r\n");
}
//REset Done

runs at 100% cpu. You may want to give the code which resets the event a bit of the cpu resource. Consider a small sleep, say Sleep(10) inside this loop.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top