0

I have written a program which simulates the producer consumer problem and I am running into a couple of issues. This was written using Win32 API.

I am using two semaphores full and empty to perform the counting for the buffer where items are stored. There is a mutex as well to control access to the critical section. I have two functions: one creates an item based on a simple calculation: threads * 1000000 + count, while the other consumes it.

The buffer has 10 spaces in it however the program should hopefully be able to work for different number of spaces and threads. The Producer thread goes through the buffer then starts over until the semaphore counts up to 10. I am running into two problems that I can't seem to find a solution too nor do I get many details in the debugger.

1) The commented part which has the printf() function crashes the thread every single time. Nothing ever gets printed to console. I have tried using just a string as well with no other variables being outputted. No success. I found documentation that printf() can run into trouble when used in a multithreaded environment however in this case it is within the critical section and it crashes on the first try. How can I print that information to console?

2) When I remove the print statements and run the code the threads still crash at different points every time. I can't figure out why. The producer thread is supposed to wait for the empty semaphore and the mutex, put the item in, then increase the count for the full semaphore (signifying an item has been added). When it reaches 10 it should stop. The Consumer thread waits for the full semaphore and the mutex, removes an item, then increases the count for the empty semaphore. Is there something in the way I've written it that is causing these thread exits?

This is what I get:

The program '[5348] OperatingSystem.exe' has exited with code 0 (0x0).

#include<stdio.h>
#include<windows.h>
#include<ctype.h>
#include<tchar.h>
#include<strsafe.h>
#include<conio.h>
#include<time.h>


#define threads 1
#define MAX 10


typedef struct objects {
HANDLE empty;
HANDLE full;
HANDLE mutex;
int buffer[10];
};


  struct objects data;


DWORD WINAPI Producers(LPVOID lpParam){
int count = 0;
int item;
while (TRUE){
    if (data.buffer[count] == 0){
        WaitForSingleObject(data.empty, INFINITE);
        WaitForSingleObject(data.mutex, INFINITE);
        item = threads * 1000000 + count;
        data.buffer[count] = item;
        //printf("Producer has produced: %d", item);
        ReleaseMutex(data.mutex);
        ReleaseSemaphore(data.full, 1, NULL);
    }
    count++;
    if (count == 10){ count = 0; }
};
}


DWORD WINAPI Consumers(LPVOID lpParam){
int count = 0;
while (TRUE){
    if (data.buffer[count] != 0){
        WaitForSingleObject(data.full, INFINITE);
        WaitForSingleObject(data.mutex, INFINITE);
        //printf("Consumer has consummed: %d", data.buffer[count]);
        data.buffer[count] = 0;
        ReleaseMutex(data.mutex);
        ReleaseSemaphore(data.empty, 1, NULL);
    }
    count++;
    if (count == 10){ count = 0; }
};



}

int main(int argc, char *argv[]) {

struct objects data;
LONG initialCount = 0;
LONG maxCount = 10;
data.empty = CreateSemaphore(NULL, maxCount, maxCount, NULL);
data.full = CreateSemaphore(NULL, initialCount, maxCount, NULL);
data.mutex = CreateMutex(NULL, FALSE, NULL);


DWORD ConsumerId[threads];
HANDLE ConsumerThread[threads];
DWORD ProducerId[threads];
HANDLE ProducerThread[threads];


for (int i = 0; i < threads; i++){
    ProducerThread[i] = CreateThread(
        NULL,
        0,
        Producers,
        NULL,
        0,
        &ProducerId[i]);


    ConsumerThread[i] = CreateThread(
        NULL,
        0,
        Consumers,
        NULL,
        0,
        &ConsumerId[i]);
}
}
TImmuh
  • 57
  • 1
  • 2
  • 10
  • 2
    It appears you haven't put any mechanism in the program to keep it from exiting before the threads do their work. One way to do this is to join the individual threads to the main thread before main() returns. – Tom Apr 12 '14 at 16:38
  • I think I get what you're saying. Put a WaitForSingleObject() for the threads in main to make sure they finish before main() returns. What is causing the printf errors though? They always cause the threads to exit. – TImmuh Apr 12 '14 at 16:57
  • OK, I can understand it terminating early 'cos main thread exits and TerminateProcess() gets called, but why should there be any crash? – Martin James Apr 12 '14 at 17:01
  • Hmm.. when multiple consumer threads try to write to sdtout, they are likely to block on the stdout mutex/CS, so it's likely that the main thread will be made running sooner than it would otherwise. Maybe that explains why a printf() call results in an earlier exit. – Martin James Apr 12 '14 at 17:06
  • `exited with code 0 (0x0)` doesn't mean crash - it means the program terminated normally, as Tom indicated. – Michael Burr Apr 12 '14 at 17:42
  • What does it look when `printf` "crashes the thread"? – Dialecticus Apr 12 '14 at 19:08
  • @Dialecticus The thread 0x1bb8 has exited with code 0 (0x0). The thread 0x2124 has exited with code 0 (0x0). The program '[7604] OperatingSystem.exe' has exited with code 0 (0x0). – TImmuh Apr 13 '14 at 05:17
  • Then nothing really crashed. Threads just exited, but that is not the same as "crashing", which usually means [exceptions of the operating system](http://msdn.microsoft.com/en-us/library/windows/desktop/ms679356.aspx), such as memory access violation, or stack overflow, or division by zero. Some even use the term for [C++ exceptions](http://msdn.microsoft.com/en-us/library/4t3saedz.aspx), or [run-time checks](http://msdn.microsoft.com/en-us/library/162azb0k.aspx), or [assertion violations](http://msdn.microsoft.com/en-us/library/ww5t02fa.aspx), but that is a wrong usage of the term. – Dialecticus Apr 13 '14 at 08:34
  • You are right. It was my mistake. printf works without a problem now that a WaitForSingleObject() has been added in the main() function to wait for the threads to finish. – TImmuh Apr 13 '14 at 19:52

0 Answers0